From f133c43e151036fe0ae9625df5ec87b756c5cd10 Mon Sep 17 00:00:00 2001 From: Jordanmuss99 <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 28 Apr 2026 19:27:33 +1000 Subject: [PATCH 01/95] =?UTF-8?q?docs:=20close=20out=20dp-20=20audit=20?= =?UTF-8?q?=E2=80=94=20remove=20resolved=20TODOs,=20update=20PROGRESS.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PROGRESS.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/PROGRESS.md b/PROGRESS.md index 77d5ec6..29578ec 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -6,9 +6,9 @@ Active implementation tracking. **Claude: Update this as you work.** ## Current Status -**Phase**: dp-19 slider→reservation-API wiring shipped -**Last Updated**: 2026-04-27 -**Last Session**: dp-19 shipped. Wired `dynamicSliderGroup` Alpine component to `POST /api/dynamic-pterodactyl/reservation`; swapped route middleware to `checkout` for guest support; made `cart_item_id` optional; added `Cart::checkout()` confirmation hook; 3 new guest tests green; CodeRabbit 2 findings fixed. +**Phase**: dp-20 reservation lifecycle close-out (shipped as part of dp-19) +**Last Updated**: 2026-04-28 +**Last Session**: dp-20 audit pass confirmed all 4 changes (cart-clear race fix, confirm-return logging, cleanup cron, expires_at guard) were already implemented in dp-19 commit `a861479`. All 128 tests green. Plan closed out. --- @@ -58,6 +58,7 @@ All documentation and scaffolding complete. 9 spec files + 4 support files (CLAU | dp-16 | Docs sync: align 03-API + 05-ADMIN-UI + 09-IMPLEMENTATION with post-dp-13 architecture | Shipped — squash `f5f88c7` (PR #19) | Apr 2026 | | dp-18 | Capacity-fanout Performance: batch admin-view Pterodactyl reads | Shipped — squash `be4756f` (PR #20) | Apr 2026 | | dp-19 | Wire customer-facing slider to reservation API (guest support) | Shipped — direct commits on `dynamic-slider` | Apr 2026 | +| dp-20 | Reservation lifecycle fixes (cart-clear race, confirm-return, cleanup cron, expires_at guard) | Shipped inside dp-19 commit `a861479` (no separate PR) | Apr 2026 | --- From a979596d6efe10d64710b17a20f51f7568585f40 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 18:59:15 +1000 Subject: [PATCH 02/95] fix(resources): batch location availability reads --- Services/ResourceCalculationService.php | 53 ++++--- tests/Unit/ResourceCalculationServiceTest.php | 130 +++++++++++++----- 2 files changed, 129 insertions(+), 54 deletions(-) diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index 696bf4d..3b66c8c 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -143,9 +143,10 @@ public function buildClusterSnapshot(): array /** * Calculate available resources for a specific node */ - private function calculateNodeAvailability(array $node, ?string $excludeReservationToken = null): array + private function calculateNodeAvailability(array $nodeWithServers, ?string $excludeReservationToken = null): array { - $servers = $this->fetchServersOnNode($node['id']); + $node = $nodeWithServers['node']; + $servers = $nodeWithServers['servers']; $pendingReservations = $this->getPendingReservations($node['id'], $excludeReservationToken); return $this->buildNodeAvailabilityFromServers($node, $servers, $pendingReservations); @@ -200,13 +201,13 @@ public function testConnection(): array public function verifyAvailability(int $nodeId, array $requirements, ?string $excludeReservationToken = null): bool { $nodes = $this->fetchNodesInLocation($this->getNodeLocation($nodeId)); - $node = \collect($nodes)->firstWhere('id', $nodeId); + $nodeWithServers = \collect($nodes)->first(fn ($n) => ($n['node']['id'] ?? null) === $nodeId); - if (! $node) { + if (! $nodeWithServers) { return false; } - $availability = $this->calculateNodeAvailability($node, $excludeReservationToken); + $availability = $this->calculateNodeAvailability($nodeWithServers, $excludeReservationToken); return $availability['available']['memory'] >= $requirements['memory'] && $availability['available']['cpu'] >= $requirements['cpu'] @@ -225,23 +226,35 @@ public function getLocations(): array private function fetchNodesInLocation(int $locationId): array { - $data = $this->pterodactylGet('/api/application/nodes', [ - 'filter[location_id]' => $locationId, - 'per_page' => 100, - ]); - - return \collect($data['data'] ?? []) - ->map(fn ($node) => $node['attributes']) - ->toArray(); - } + $response = $this->pterodactylGet( + "/api/application/locations/{$locationId}", + ['include' => 'nodes,servers'] + ); + + $nodesData = $response['attributes']['relationships']['nodes']['data'] ?? []; + $serversData = $response['attributes']['relationships']['servers']['data'] ?? []; + + // Group servers by node_id for per-node allocation accounting + $serversByNode = []; + foreach ($serversData as $server) { + $nodeId = $server['attributes']['node'] ?? null; + if ($nodeId === null) { + continue; + } + $serversByNode[$nodeId][] = $server['attributes']; + } - private function fetchServersOnNode(int $nodeId): array - { - $data = $this->pterodactylGet("/api/application/nodes/{$nodeId}", ['include' => 'servers']); + $nodes = []; + foreach ($nodesData as $node) { + $attrs = $node['attributes']; + $nodeId = $attrs['id']; + $nodes[] = [ + 'node' => $attrs, + 'servers' => $serversByNode[$nodeId] ?? [], + ]; + } - return \collect($this->extractRelationshipData($data, 'servers')) - ->map(fn ($server) => $server['attributes']) - ->toArray(); + return $nodes; } private function buildNodeAvailabilityFromServers(array $node, array $servers, array $pendingReservations): array diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index 0b38c69..6db6af8 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -192,6 +192,26 @@ public function test_verify_availability_without_exclusion_fails_on_edge_fit(): $this->assertFalse($this->service->verifyAvailability(5, $resources)); } + public function test_location_availability_groups_included_servers_by_node(): void + { + Http::fake($this->availabilityHttpFake( + nodeId: 5, + locationId: 1, + totalMemory: 8192, + totalDisk: 51200, + totalCpuThreads: 4, + servers: [ + ['node' => 5, 'memory' => 1024, 'cpu' => 50, 'disk' => 5120], + ['node' => 6, 'memory' => 4096, 'cpu' => 200, 'disk' => 20480], + ], + )); + + $result = $this->service->getLocationAvailability(1); + + $this->assertSame(['memory' => 1024, 'cpu' => 50, 'disk' => 5120], $result['nodes'][0]['allocated']); + $this->assertSame(['memory' => 7168, 'cpu' => 350, 'disk' => 46080], $result['nodes'][0]['available']); + } + public function test_snapshot_with_single_location_single_node(): void { $calls = 0; @@ -251,29 +271,35 @@ public function test_snapshot_aggregates_across_locations(): void $this->assertLessThanOrEqual(4, $calls); } - public function test_snapshot_handles_paginated_node_response(): void + public function test_snapshot_handles_paginated_location_response(): void { $calls = 0; Http::fake($this->clusterSnapshotHttpFake( $calls, locations: [ - ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1'], + [ + ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1'], + ['id' => 2, 'short' => 'dc2', 'long' => 'Data Center 2'], + ], + [ + ['id' => 3, 'short' => 'dc3', 'long' => 'Data Center 3'], + ], ], nodePages: [ [ $this->nodeWithServersPayload(1, 1, 'Node 1', []), - $this->nodeWithServersPayload(2, 1, 'Node 2', []), - ], - [ - $this->nodeWithServersPayload(3, 1, 'Node 3', []), + $this->nodeWithServersPayload(2, 2, 'Node 2', []), + $this->nodeWithServersPayload(3, 3, 'Node 3', []), ], ], )); $snapshot = $this->service->buildClusterSnapshot(); - $this->assertSame([1, 2, 3], $snapshot['by_location'][1]['nodes']); + $this->assertSame([1], $snapshot['by_location'][1]['nodes']); + $this->assertSame([2], $snapshot['by_location'][2]['nodes']); + $this->assertSame([3], $snapshot['by_location'][3]['nodes']); $this->assertCount(3, $snapshot['nodes']); $this->assertLessThanOrEqual(4, $calls); } @@ -349,36 +375,64 @@ private function insertPendingReservation(string $token, int $nodeId, int $locat ]); } - private function availabilityHttpFake(int $nodeId, int $locationId, int $totalMemory, int $totalDisk, int $totalCpuThreads): callable + private function availabilityHttpFake( + int $nodeId, + int $locationId, + int $totalMemory, + int $totalDisk, + int $totalCpuThreads, + array $servers = [], + ): callable { - return function ($request) use ($nodeId, $locationId, $totalMemory, $totalDisk, $totalCpuThreads) { + return function ($request) use ($nodeId, $locationId, $totalMemory, $totalDisk, $totalCpuThreads, $servers) { $url = $request->url(); + $query = []; + parse_str(parse_url($url, PHP_URL_QUERY) ?? '', $query); - if (str_contains($url, '/api/application/nodes?')) { - return Http::response([ - 'data' => [[ - 'attributes' => [ - 'id' => $nodeId, - 'location_id' => $locationId, - 'name' => 'Node '.$nodeId, - 'fqdn' => 'node-'.$nodeId.'.example.com', - 'memory' => $totalMemory, - 'disk' => $totalDisk, - 'cpu_threads' => $totalCpuThreads, - 'memory_overallocate' => 0, - 'disk_overallocate' => 0, - 'maintenance_mode' => false, - ], - ]], - ], 200); - } - - if (str_contains($url, "/api/application/nodes/{$nodeId}?include=servers")) { + if (str_contains($url, "/api/application/locations/{$locationId}") && ($query['include'] ?? null) === 'nodes,servers') { return Http::response([ + 'object' => 'location', 'attributes' => [ + 'id' => $locationId, + 'short' => 'dc'.$locationId, + 'long' => 'Data Center '.$locationId, 'relationships' => [ + 'nodes' => [ + 'object' => 'list', + 'data' => [[ + 'object' => 'node', + 'attributes' => [ + 'id' => $nodeId, + 'location_id' => $locationId, + 'name' => 'Node '.$nodeId, + 'fqdn' => 'node-'.$nodeId.'.example.com', + 'memory' => $totalMemory, + 'disk' => $totalDisk, + 'cpu_threads' => $totalCpuThreads, + 'memory_overallocate' => 0, + 'disk_overallocate' => 0, + 'maintenance_mode' => false, + 'allocated_resources' => [ + 'memory' => 0, + 'disk' => 0, + ], + ], + ]], + ], 'servers' => [ - 'data' => [], + 'object' => 'list', + 'data' => array_map(fn (array $server, int $index) => [ + 'object' => 'server', + 'attributes' => [ + 'id' => ($server['node'] * 100) + $index, + 'node' => $server['node'], + 'limits' => [ + 'memory' => $server['memory'], + 'cpu' => $server['cpu'], + 'disk' => $server['disk'], + ], + ], + ], $servers, array_keys($servers)), ], ], ], @@ -407,13 +461,16 @@ private function clusterSnapshotHttpFake(int &$calls, array $locations, array $n $query = []; parse_str(parse_url($url, PHP_URL_QUERY) ?? '', $query); - if (str_contains($url, '/api/application/locations')) { + if (str_contains($url, '/api/application/locations') && ! preg_match('#/api/application/locations/\d+#', $url)) { + $locationPages = $this->isPaginatedPayload($locations) ? $locations : [$locations]; + $page = (int) ($query['page'] ?? 1); + return Http::response([ - 'data' => array_map(fn (array $location) => ['attributes' => $location], $locations), + 'data' => array_map(fn (array $location) => ['attributes' => $location], $locationPages[$page - 1] ?? []), 'meta' => [ 'pagination' => [ - 'current_page' => 1, - 'total_pages' => 1, + 'current_page' => $page, + 'total_pages' => count($locationPages), ], ], ], 200); @@ -437,6 +494,11 @@ private function clusterSnapshotHttpFake(int &$calls, array $locations, array $n }; } + private function isPaginatedPayload(array $payload): bool + { + return isset($payload[0]) && is_array($payload[0]) && array_is_list($payload[0]); + } + private function nodeWithServersPayload(int $nodeId, int $locationId, string $name, array $servers): array { return [ From 35ac1959f944151ce680bd5d2293bfc35ef3e70f Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 18:59:51 +1000 Subject: [PATCH 03/95] test: support standalone Paymenter checkouts --- phpunit.xml | 1 + tests/LaravelTestCase.php | 9 ++++++++- tests/bootstrap.php | 26 ++++++++++++++++++++++---- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/phpunit.xml b/phpunit.xml index 9a2d06f..90dae74 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -27,6 +27,7 @@ + diff --git a/tests/LaravelTestCase.php b/tests/LaravelTestCase.php index aac8b77..c6446ab 100644 --- a/tests/LaravelTestCase.php +++ b/tests/LaravelTestCase.php @@ -12,12 +12,19 @@ abstract class LaravelTestCase extends BaseTestCase */ public function createApplication() { - $bootstrap = __DIR__ . '/../../../../bootstrap/app.php'; + $paymenterBasePath = getenv('PAYMENTER_BASE_PATH'); + $bootstrap = $paymenterBasePath + ? rtrim($paymenterBasePath, '/\\') . '/bootstrap/app.php' + : __DIR__ . '/../../../../bootstrap/app.php'; if (!file_exists($bootstrap)) { $bootstrap = '/var/www/paymenter/bootstrap/app.php'; } + if (!file_exists($bootstrap)) { + throw new \RuntimeException('Unable to locate Paymenter bootstrap/app.php. Set PAYMENTER_BASE_PATH for standalone checkouts.'); + } + $app = require $bootstrap; $app->make(Kernel::class)->bootstrap(); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index e4bde8c..dfe05b3 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,18 +1,36 @@ addPsr4( + 'Paymenter\\Extensions\\Others\\DynamicPterodactyl\\', + dirname(__DIR__) . '/', +); // dp-13 guard: refuse to boot against a non-test database. $db = getenv('DB_DATABASE') ?: ($_ENV['DB_DATABASE'] ?? ''); -if ($db !== 'paymenter_test' && $db !== ':memory:' && $db !== '') { +$connection = getenv('DB_CONNECTION') ?: ($_ENV['DB_CONNECTION'] ?? ''); +$appEnvironment = getenv('APP_ENV') ?: ($_ENV['APP_ENV'] ?? ''); +$isSqliteTestDatabase = $appEnvironment === 'testing' + && $connection === 'sqlite' + && ($db === ':memory:' || str_ends_with(strtolower($db), '.sqlite')); + +if ($db !== 'paymenter_test' && $db !== '' && ! $isSqliteTestDatabase) { fwrite(STDERR, "ABORT: phpunit would run against DB_DATABASE='$db'. " - . "Expected 'paymenter_test' or ':memory:'. See .sisyphus/notepads/dp-11-authorization-surface-reduction/incidents.md.\n"); + . "Expected 'paymenter_test' or a testing-only SQLite database. " + . "See .sisyphus/notepads/dp-11-authorization-surface-reduction/incidents.md.\n"); exit(2); } From f652667a39571cbd2991fa9469220e7cfff99440 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 19:03:22 +1000 Subject: [PATCH 04/95] docs: refresh availability security wiki --- .../Availability Endpoints.md | 97 ++++++++++++++++--- .../repowiki/en/meta/repowiki-metadata.json | 2 +- 2 files changed, 85 insertions(+), 14 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md index 7a81b42..2d71405 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md @@ -11,22 +11,30 @@ - [DECISIONS.md](file://DECISIONS.md) +## Update Summary +**Changes Made** +- Enhanced security section with new test assertions for preventing node-level data exposure +- Updated endpoint specification to emphasize security boundaries +- Added comprehensive security testing coverage details +- Strengthened error handling documentation with security considerations + ## Table of Contents 1. [Introduction](#introduction) 2. [Project Structure](#project-structure) 3. [Core Components](#core-components) 4. [Architecture Overview](#architecture-overview) 5. [Detailed Component Analysis](#detailed-component-analysis) -6. [Dependency Analysis](#dependency-analysis) -7. [Performance Considerations](#performance-considerations) -8. [Troubleshooting Guide](#troubleshooting-guide) -9. [Conclusion](#conclusion) +6. [Security and Data Exposure Prevention](#security-and-data-exposure-prevention) +7. [Dependency Analysis](#dependency-analysis) +8. [Performance Considerations](#performance-considerations) +9. [Troubleshooting Guide](#troubleshooting-guide) +10. [Conclusion](#conclusion) ## Introduction -This document specifies the customer-facing availability endpoint that returns aggregate, location-based capacity data for Pterodactyl nodes. It covers authentication, rate limiting, request/response schemas, error handling, and performance characteristics. The endpoint is designed to answer “what can I get at this location right now?” without exposing node-level internals to customers. +This document specifies the customer-facing availability endpoint that returns aggregate, location-based capacity data for Pterodactyl nodes. It covers authentication, rate limiting, request/response schemas, error handling, performance characteristics, and comprehensive security measures designed to prevent node-level data exposure to customers. The endpoint is designed to answer "what can I get at this location right now?" without exposing node-level internals to customers. ## Project Structure -The availability feature spans routes, a controller, and services that call the Pterodactyl API in real time. Customer endpoints are grouped under a single route prefix with shared middleware for session-based authentication and throttling. +The availability feature spans routes, a controller, and services that call the Pterodactyl API in real time. Customer endpoints are grouped under a single route prefix with shared middleware for session-based authentication and throttling. Security measures ensure that only aggregate data is returned to customers while detailed node information remains admin-only. ```mermaid graph TB @@ -36,6 +44,8 @@ MW --> Ctrl["AvailabilityController::getByLocation"] Ctrl --> NodeSel["NodeSelectionService::getMaxAvailable"] Ctrl --> ResCalc["ResourceCalculationService::getLocationAvailability"] ResCalc --> Ptero["Pterodactyl API"] +Ctrl --> Security["Security Layer
Data Sanitization"] +Security --> Response["Secure JSON Response
No Node Details"] ``` **Diagram sources** @@ -49,7 +59,7 @@ ResCalc --> Ptero["Pterodactyl API"] ## Core Components - Route group: Defines the public availability endpoint and applies session-based authentication and rate limiting. -- Controller: Orchestrates aggregation and returns a simplified response to customers. +- Controller: Orchestrates aggregation and returns a simplified response to customers with built-in security sanitization. - Services: - NodeSelectionService: Computes maximum allocatable resources across a location. - ResourceCalculationService: Fetches live node/server data from Pterodactyl and aggregates totals and per-node details (used internally and by admin). @@ -59,6 +69,7 @@ Key responsibilities: - Throttle requests to protect downstream Pterodactyl API budget. - Aggregate per-location maxima for memory, CPU, and disk. - Provide a boolean flag indicating whether all three resources have positive availability. +- **Enhanced**: Ensure no node-level data leaks to customer responses through comprehensive testing and validation. **Section sources** - [routes/api.php:17-22](file://routes/api.php#L17-L22) @@ -72,6 +83,7 @@ The GET /api/dynamic-pterodactyl/availability/{locationId} flow: 2. AvailabilityController::getByLocation resolves max available resources via NodeSelectionService. 3. It also fetches location availability via ResourceCalculationService to compute node_count and resource_capacity booleans. 4. A compact JSON response is returned with only aggregate fields; no node identifiers or internal details are exposed. +5. **Enhanced**: Comprehensive test coverage ensures security boundaries are maintained. ```mermaid sequenceDiagram @@ -93,6 +105,7 @@ S-->>N : Aggregated availability N-->>A : Max available {memory, cpu, disk} A->>S : getLocationAvailability(locationId) S-->>A : Location data including nodes[] +A->>A : Security sanitization
Remove node details A-->>C : {success, data : {location_id, max_memory, max_cpu, max_disk, node_count, has_capacity, resource_capacity}} ``` @@ -172,10 +185,11 @@ Error handling - Pterodactyl API failures: - Network timeouts, connection errors, or non-2xx responses result in exceptions thrown by the service layer and surfaced as success: false with a descriptive message. - Rate limiting exceeded: - - Requests beyond 30 per minute receive a standard throttle response from the framework’s throttle middleware. + - Requests beyond 30 per minute receive a standard throttle response from the framework's throttle middleware. Why node-level details are not exposed -- Customer-facing endpoints intentionally return only aggregate per-location maxima and counts. Node names, FQDNs, maintenance flags, and per-node capacities are reserved for admin-only access. This reduces information leakage and keeps the customer experience focused on “can I buy here?” rather than infrastructure specifics. +- Customer-facing endpoints intentionally return only aggregate per-location maxima and counts. Node names, FQDNs, maintenance flags, and per-node capacities are reserved for admin-only access. This reduces information leakage and keeps the customer experience focused on "can I buy here?" rather than infrastructure specifics. +- **Enhanced Security**: Comprehensive test coverage ensures that node-level data never leaks to customer responses through automated assertions. **Section sources** - [routes/api.php:17-22](file://routes/api.php#L17-L22) @@ -203,7 +217,7 @@ ForEachNode --> |No| ReturnData["Return {location_id, nodes[], max_available, to ``` **Diagram sources** -- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) +- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-67) - [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) **Section sources** @@ -224,6 +238,46 @@ ForEachNode --> |No| ReturnData["Return {location_id, nodes[], max_available, to - [routes/api.php:32-40](file://routes/api.php#L32-L40) - [EnsureUserIsAdmin.php:9-21](file://Http/Middleware/EnsureUserIsAdmin.php#L9-L21) +## Security and Data Exposure Prevention + +### Enhanced Security Measures +The system implements comprehensive security measures to prevent node-level data exposure in customer responses: + +#### Test Coverage for Security Boundaries +- **Automated Assertions**: Tests explicitly verify that the 'nodes' key is never present in customer-facing availability responses +- **Security Validation**: Both positive and negative capacity scenarios include assertions to ensure data isolation +- **Mock Testing**: Service mocks simulate realistic scenarios while maintaining security boundaries + +#### Security Implementation Details +- **Response Sanitization**: Customer endpoints return only aggregate data (max_memory, max_cpu, max_disk, node_count) +- **Admin Isolation**: Detailed node information is exclusively available through admin-only endpoints with proper authorization +- **Data Minimization**: Even when internal services process node-level data, it is never exposed to customer responses + +#### Security Testing Examples +The test suite includes comprehensive security validation: +- Verifies absence of 'nodes' key in customer responses +- Tests both capacity-available and capacity-exhausted scenarios +- Ensures consistent security behavior across different resource states + +```mermaid +flowchart TD +CustomerReq["Customer Request"] --> AuthCheck["Authentication Check"] +AuthCheck --> SecurityLayer["Security Layer"] +SecurityLayer --> DataAggregation["Aggregate Data Only"] +DataAggregation --> SecurityValidation["Security Validation
(No node details)"] +SecurityValidation --> TestCoverage["Automated Test Coverage"] +TestCoverage --> SecureResponse["Secure Response
(Aggregate only)"] +``` + +**Diagram sources** +- [AvailabilityApiTest.php:48-49](file://tests/Feature/AvailabilityApiTest.php#L48-L49) +- [AvailabilityApiTest.php:77-78](file://tests/Feature/AvailabilityApiTest.php#L77-L78) + +**Section sources** +- [AvailabilityApiTest.php:48-49](file://tests/Feature/AvailabilityApiTest.php#L48-L49) +- [AvailabilityApiTest.php:77-78](file://tests/Feature/AvailabilityApiTest.php#L77-L78) +- [DECISIONS.md:237-239](file://DECISIONS.md#L237-L239) + ## Dependency Analysis ```mermaid classDiagram @@ -242,20 +296,29 @@ class ResourceCalculationService { +testConnection() array +getLocations() array } +class AvailabilityApiTest { ++test_has_capacity_false_when_cpu_exhausted_but_memory_positive() void ++test_has_capacity_true_when_all_resources_positive() void ++bindAvailabilityServices(maxAvailable) void +} AvailabilityController --> NodeSelectionService : "uses" AvailabilityController --> ResourceCalculationService : "uses" NodeSelectionService --> ResourceCalculationService : "delegates" +AvailabilityApiTest --> NodeSelectionService : "mocks" +AvailabilityApiTest --> ResourceCalculationService : "mocks" ``` **Diagram sources** - [AvailabilityController.php:9-20](file://Http/Controllers/Api/AvailabilityController.php#L9-L20) - [NodeSelectionService.php:5-12](file://Services/NodeSelectionService.php#L5-L12) - [ResourceCalculationService.php:10-21](file://Services/ResourceCalculationService.php#L10-L21) +- [AvailabilityApiTest.php:12-100](file://tests/Feature/AvailabilityApiTest.php#L12-L100) **Section sources** - [AvailabilityController.php:9-20](file://Http/Controllers/Api/AvailabilityController.php#L9-L20) - [NodeSelectionService.php:5-12](file://Services/NodeSelectionService.php#L5-L12) - [ResourceCalculationService.php:10-21](file://Services/ResourceCalculationService.php#L10-L21) +- [AvailabilityApiTest.php:12-100](file://tests/Feature/AvailabilityApiTest.php#L12-L100) ## Performance Considerations - Real-time data fetching: @@ -268,8 +331,7 @@ NodeSelectionService --> ResourceCalculationService : "delegates" - 30 req/min protects against excessive load on the Pterodactyl API and mitigates abuse. - Database reads: - Pending reservations are summed per node to adjust available capacity accurately at query time. - -[No sources needed since this section provides general guidance] +- **Enhanced**: Security validation adds minimal overhead through automated testing but ensures long-term security posture without runtime performance impact. ## Troubleshooting Guide Common issues and how they manifest: @@ -283,15 +345,24 @@ Common issues and how they manifest: - Network timeouts, connection failures, or non-2xx responses cause exceptions in the service layer; these are caught and returned as success: false with a message and error details. - Unexpected payload: - Malformed or non-JSON responses from Pterodactyl are treated as errors and logged for diagnostics. +- **Enhanced**: Security validation failures: + - If tests detect node-level data exposure, investigate the response structure and ensure proper sanitization in the controller layer. Verification tips - Confirm you are authenticated via a valid session cookie. - Ensure your client respects the throttle limits and implements exponential backoff. - Validate that the locationId exists in your Pterodactyl instance. +- **Enhanced**: Run security tests to verify no node-level data exposure in responses. **Section sources** - [AvailabilityController.php:45-51](file://Http/Controllers/Api/AvailabilityController.php#L45-L51) - [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [AvailabilityApiTest.php:48-49](file://tests/Feature/AvailabilityApiTest.php#L48-L49) +- [AvailabilityApiTest.php:77-78](file://tests/Feature/AvailabilityApiTest.php#L77-L78) ## Conclusion -The GET /api/dynamic-pterodactyl/availability/{locationId} endpoint provides a secure, rate-limited, and real-time view of aggregate capacity for a given location. It exposes only what customers need to make purchasing decisions—maximum allocatable memory, CPU, and disk, along with a simple capacity indicator—while keeping node-level internals private. Errors are handled consistently, and performance is optimized through batched API calls and careful timeout/retry policies. \ No newline at end of file +The GET /api/dynamic-pterodactyl/availability/{locationId} endpoint provides a secure, rate-limited, and real-time view of aggregate capacity for a given location. It exposes only what customers need to make purchasing decisions—maximum allocatable memory, CPU, and disk, along with a simple capacity indicator—while keeping node-level internals private. + +**Enhanced Security**: The system now includes comprehensive automated testing to ensure that node-level data never leaks to customer responses. These security measures provide confidence that the data boundary between customer and admin interfaces remains intact, protecting sensitive infrastructure information while delivering accurate capacity information to customers. + +Errors are handled consistently, performance is optimized through batched API calls and careful timeout/retry policies, and security is enforced through both architectural design and comprehensive test coverage. diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 0d7be4b..ac050db 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":99,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:48:47.8218489+10:00","gmt_modified":"2026-08-14T18:48:47.8218489+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:43:09.3742295+10:00","raw_data":"WikiEncrypted:k297iOFQy9oqfJmcEkC3d77ZGM/0+lgF8c5KNHlKBcZGKhgG6RupM5f5pti32Y7jK1BHd1ueLOV7zFCDZP1LVkTrVAmwqml3NNnf9QMI8Vd5JZQiKdsecTEySGm5GQu8Jn3yHVAqGBLEMnB0TAvWSqJKQ4yNFF2fCb/eMSndVvWcf52C5alxlhFQFDCS/pU6Z9pjZ/rv422zTBKvRExfKRc+c1sufXc5psdtsh7T8b/YQWinN6XR2kq+Jhg1+JOYW22lbLXLKV+8+rHmjOnT2+Vq5xoB63ciSHVb/0vn5phyPIgWJZirMtiE0uzHBXI3GhEZ52CvUrzbjg4N1M2+oY5swqBnX5QVHqduQ15EQ/MpmWeyd+lzSFAKFC981JJsuaIGXjnm34htiQAs93ngUPA4i8FAf0lEi5vqmIvMhgVsV4I3xCgnSlHTyLO+QDKgYvXztsHxOx5jk3v4GVQljuEpsEbFygbznyzqHjyJKo4xWW1BoCTUHTKr/BtP/+mAPClbgo9rCuNeOQWAYcON1NMkLsk2yudNhIgJYqnctGQCqssurQL3u9Bwhh2qy5dj/8zZ7ri08RSMTJzEgSL0PE8foCxmzBKfejGIHzblcNZWmDhPGAAHggx1WfyTesdUXVou94vCdn7AbOwQfpw/oiB8GXYUP3Xuk2iuoM8Wi3pC6MIcCxOEJEjyyBKn2f9DKA4mNAOrTgW5PTTiypwXUK8QZJQXSHA/V639EfuTGX92Bk7s/OjYaBf92/c90JrkSKfNF6s/PclVGef1YwaB3r6iPqp0mboAcChfGgINfj0atx+Oq6ynZ7JxIK4QNLkAPeyO5Mc3/OjZZNU4Yr+YZsNDnorcKTnBPknRk2OYiMCvbdGjtEumLjOVYsPOf/Qk6Hk+7ViodjVVblVtuMDLSATuq4H2mTS0+bOrUqHkNyeOmCkJM4TSnM5wYvG2hDCXavGjCG7oqAYbZq495Vy1HGMxai+WPPGIZIOmHuFrPb5EuI8cG0JZa380jf6d/qbMSQEK3Tngv7iS9Ds7wv87qTtXQYNoTUiq1JtcCsEiT5klUbBjAcIUeVs0Voju2GVdtE6ULFLheuimhH/UgpiwgQQz0Pr5gGteArsxM3PZdWZYFj4JzmrmHOMV9WCQU4scFzWDNDk3m98mO9hPClbrEMcMuzmTafkISDHD5+CFg/1GdHkFpQvDki/GWAv2B7aKanjuiuBsCHUTwFYK6SDa8UikzbxzKoYV/Ir9XyxfDsqqmfCwt6mJ0pgvSNqyyOogw0ONN186igFL1SfS+bJU14SIDSMjroSm+32ZznjptTYaeXFO9qVBY2FHv8An+9xTofB5TeSRMYNNcFQHmze+NZw/KH6XPLUBjX80oMyfmjIe1XIRE55PdBl16Qv2kREC0w11OcuP3Njc4FN2mNm8xujDufrYWLwUBkvdSll3Qz4k4NKUfoNB5FkEXd4b9zJq56t5g/X44szhhYFrCr3LTesXEGWSKakeSNmGvTeJaJA54qhUFIFJfu4qhdwL502cJsK+7opvVKaOYuL2bJ6sdEYoFTw82eQpbuzzmpoY9+qZfBCDPcrnrz7XaMqjAny+NT3L4oKiylqrRtDLwdtd9+2p0JVhXv8xmxTcik9A8vV1TuuVLvYZJ0rFCEMkgJG5ORr62EvbqzCXXHGLIiyoRPogtKsTBQyV1TWl92jHlloT4vPMjbS06v1Fv6LeFMvPvcSgQS1z8goOlyNCc+7uXg==","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T18:43:09.3747486+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"bba642c046ad0dfd91f8ff402787369549124486","last_commit_update":"2026-08-14T18:48:47.8309011+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T18:48:47.8309011+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-86","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"247-289","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"452-498","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBW0kY68nN6yH347gACSKnGW/GaWsrfe1qmD5Vs4yiF9Bg4+cNg243x5/lrCPGe0ZLa727Kgt90Uf0qPTmGz2CCcagpDlxGuQ7KqPUQcnjLaS5faJVmqkBWfw6JX8uB8qtdCgeBozoNT8CS3Bl+VaFcrfo46PhuL+4MV4UlG69rB+KEYv2FlCDFDg9dsS+3XTkwBCvSqfvBNpmup+JH+w/q41CDiYfTbbURVO8q98JASJEHxb7rNSya1EFRu03Dndw5/hcunp6sW3i/mUBf3rxpXMRj7LhAAzagrVZYsK5LpuTLXislaMmRF+QNJZ+IT2lA/DQouhtUWc62leDrTc90zHDuF0e3jmfC8eu07DCVNzcVaikeY2HvQANYSq9rcpC9dzQDVFpKkVZPyhummuPO6U99ZLXQfwklIsKdCVTSZVinDVknwHBRxCYkuHbrR8PCWVfl3nrZOl4z3lC/mgPD7igYiJ64AUnOrpRNW3FBxgRf+8BvCrHeO/WIMVcJAbwWpx1XZdbGR+ktnHoWF73udn49QqG7nwtZCHkmejnF7RE14lQ8+LnaecPtPbDVehaKMSZUoX61sD47oraIoF5YU4E4zx2W6+7KWhB+NpL6ko1IG+UcHaD4hkEfJeD/2SeBD7vRpayej1ACgV5vne+TGzI7kZjsnKCjMqmxL4YD2RzBYMKD6LQL6+ubIXcmtFJAr/Qf1KdnxmlKveyXnZvX/ndj/g4n7iBoa+G06u5nlxnDftLOS1UX5Akt9Sa4ReIpPgc+Iu4fZiEvIogShhlx03pJAKPKeqY42rc4Hmh/zj2ffRkETYofbIvn6wCSpMGtQgaNCIsoTBzZqBh0tM7Ms2F9sOuNc6VOVytLWrAGs3Uj9mAw1cTz5V3dDkS8Iqc+2KwYHX1PPfXqBnFJ9XWfpzrzj1AUpLdt2Z96y1BKsDO8FeK7GHaIwMaAh0x3oc2MEQ48zBkemSFRqIbRb6rRjJaXwqbblx57l65FhBcMxFJxsPldnLySuNmXFfz1BkfSZ5DNpDxfbRaWAgJ5iptfMKdXbJy30ubNAJBkJhH4W4vLOQclfbDxGrO05ifqQbqraigV+gsHDqbEOiWWDQntcPu4du6DA+lClzPznkDuMn7ja/xjWhR8ohc2fY4GLWlOImAZLQEAyJmjJuZjDb+wqcLkwv/j9SeZbOJGELa6Y6Cr8itehW5lwWc5TsSfqavSxmD9CM2kCWNa9KxKdXaIxsUdn3AszUAdFlaPjG1P92QEIZMq5VR63US8SMFRS/lg2Bu/R10wr78W2ugpCg5hl4fZ5p/1vmKfSOK9ausuHQkeqqTABqn+iCT1Z7fU7QiEJ1KksgoDFkz8d4juqNhT7IjgBmnKpjlFLoMF070nLjTwO0MpA2l6ecAQhNFxkCTTgbwRAIdm91gS5JWtJnfYT+O23P17YXLCRKgLW9r5xM89j/ujErpG3/BIYXQkGGTGjTpO/lzd6VuHMlCDRwq73TZwT6AUgKKmb39ODafcEgXDC0Bwj49ZcUbc5EUw20RKYOccxNuKtBfilv6f7hbd8Hu0elrwUXFysMGHrQEIp5zXnFc3NBoJTtz5sGtxvwxy8KxeukwOhTloRknS/PinVWgDSl7tIsvU41/UPsEcjYzvczZ7nHfW+gpamwJoBNcYBOgGuCXoh+r/X+5NP4J0E8n/b2wCID44OPvacVG4V0qgjxQD4xvuliHGhoyte4iUvy5yOLrxbtwVmw5WBJUPAVwPgvGGRdqqVGnUW9k5T6rUGgAYhhHc5FTr9y4OibhX47uWd5eEv8IHnOhQT5/OyBAM1DOPcI1CQf0W6Pe/UObhm1662/8HXjlFAWsAJiyHi+I4iqPHBoOO9+l5Ng9s7uFUXtS6a2de/JIymAUP30+H8rrNsAGFKDIDiIVgJoPtOqSM+8eDo5CQvS/Wtf9VNIbJ0jbt8M9D79XxKedIjsFMGtgC4JPtycHOsQu3VsEvlFdhN60jr0Dd8w2Fa1hkc=","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"53ce981e551c2c7b4b2f9bc49ee0c60654c40364","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file From b9783935802b8489ecbb887bde7b6c353e882480 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 19:40:44 +1000 Subject: [PATCH 05/95] test: harden standalone database isolation --- DECISIONS.md | 2 +- tests/AGENTS.md | 6 +-- tests/TestDatabaseGuard.php | 29 +++++++++++++ tests/Unit/ResourceCalculationServiceTest.php | 8 ++++ tests/Unit/TestDatabaseGuardTest.php | 43 +++++++++++++++++++ tests/bootstrap.php | 13 +++--- 6 files changed, 92 insertions(+), 9 deletions(-) create mode 100644 tests/TestDatabaseGuard.php create mode 100644 tests/Unit/TestDatabaseGuardTest.php diff --git a/DECISIONS.md b/DECISIONS.md index ebf655d..ac54ab6 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -244,7 +244,7 @@ Unit coverage accepted for dp-06. The full Filament-action lifecycle end-to-end ### 6. Test Isolation Mandate (dp-13, Apr 2026) -Extension phpunit MUST set `CACHE_STORE=array`, `SESSION_DRIVER=array`, `QUEUE_CONNECTION=sync`, `MAIL_MAILER=array`, `BCRYPT_ROUNDS=4`, `PULSE_ENABLED=false`, `TELESCOPE_ENABLED=false` — mirroring the root `phpunit.xml`. Failure to do so risks polluting the shared Redis/file cache on a development host, corrupting the settings key read by running web workers. This caused a production outage on 2026-04-23. The `bootstrap.php` guard provides a second line of defence (aborts if `DB_DATABASE` is not a recognised test DB). See `incidents.md` for forensics. +Extension phpunit MUST set `CACHE_STORE=array`, `SESSION_DRIVER=array`, `QUEUE_CONNECTION=sync`, `MAIL_MAILER=array`, `BCRYPT_ROUNDS=4`, `PULSE_ENABLED=false`, `TELESCOPE_ENABLED=false` — mirroring the root `phpunit.xml`. Failure to do so risks polluting the shared Redis/file cache on a development host, corrupting the settings key read by running web workers. This caused a production outage on 2026-04-23. The `bootstrap.php` guard provides a second line of defence: it accepts only `paymenter_test`, `:memory:`, or a strictly named `dynamic-pterodactyl-test-*.sqlite` file directly inside the system temp directory. Empty database names and arbitrary SQLite paths remain forbidden. See `incidents.md` for forensics. ### 7. SetupWizard Atomicity Contract (dp-13, Apr 2026) diff --git a/tests/AGENTS.md b/tests/AGENTS.md index 14cf2ee..ba3c87d 100644 --- a/tests/AGENTS.md +++ b/tests/AGENTS.md @@ -23,7 +23,7 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p | Task | Start at | Notes | |---|---|---| -| Harness boot / DB safety | `bootstrap.php`, `../phpunit.xml` | `paymenter_test` / `:memory:` guard is enforced before app boot | +| Harness boot / DB safety | `bootstrap.php`, `TestDatabaseGuard.php`, `../phpunit.xml` | `paymenter_test`, `:memory:`, or a strictly named disposable SQLite file in the system temp directory is enforced before app boot | | Lightweight service seam | `TestCase.php` | Mockery cleanup, `createPricingConfig()`, `createNodeData()`, `standardResources()` | | App-backed test seam | `LaravelTestCase.php` | Paymenter kernel boot, `createConfigOption()`, slider defaults, node fixtures | | Reservation state / audits | `Unit/ReservationServiceTest.php` | Mixes facade mocks and real DB assertions under transactions | @@ -40,7 +40,7 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p - Any DB-writing test must use `Illuminate\Foundation\Testing\DatabaseTransactions`; this includes DB-backed `Unit/` tests and all current API feature tests. - Feature API tests must `require __DIR__ . '/../../routes/api.php';` in `setUp()` because extension routes are loaded manually by `DynamicPterodactyl::boot()` at runtime. - For schedule assertions, boot the extension in the test and inspect `app(Schedule::class)->events()`; no local Job/Command classes exist. -- The bootstrap refuses unsafe databases: `DB_DATABASE` must be `paymenter_test`, `:memory:`, or empty before Laravel boots. +- The bootstrap refuses unsafe databases: `DB_DATABASE` must be `paymenter_test`, `:memory:`, or a `dynamic-pterodactyl-test-*.sqlite` file directly inside the system temp directory before Laravel boots. An empty value is rejected so the application cannot fall through to a production `.env` database after the guard runs. - `phpunit.xml` fixes testing env, `MAIL_MAILER=array`, `SESSION_DRIVER=array`, `CACHE_STORE=array` with legacy `CACHE_DRIVER=file`, sync queue, and service-source warning restrictions. - Use shared fixture helpers before creating local copies: `standardResources()`, `createNodeData()`, `createConfigOption()`, and per-file helpers such as configured products/cart items. - Common fakes are `Mockery` service/container bindings, `Http::fake()` with `Http::preventStrayRequests()` for panel calls, `Notification::fake()`, `Event::fake()`, `Log::spy()`, `Config::set()`, and `Gate::policy()`. @@ -55,7 +55,7 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p - Do not put app/factory/facade tests on raw `TestCase` except the existing separate-process `AlertService` facade isolation seam. - Do not claim `Unit/` files are all pure units; several intentionally boot Laravel and write DB rows. - Do not duplicate root command blocks, generic PHPUnit advice, or project-wide anti-patterns here. -- Do not loosen the `paymenter_test` / `:memory:` bootstrap guard. +- Do not broaden the database guard beyond `paymenter_test`, `:memory:`, or the validated disposable system-temp SQLite naming contract. - Do not add live Pterodactyl network calls; fake panel HTTP explicitly and prevent strays when testing capacity reads. - Do not expose or assert full reservation tokens in audit payloads; assert `token_prefix` behavior. - Current direct coverage gaps to watch: `CartItemCreatedListener`, `ServiceCreatedListener`, `PricingController::getConfig()`, and `AuditLogService` retrieval methods. diff --git a/tests/TestDatabaseGuard.php b/tests/TestDatabaseGuard.php new file mode 100644 index 0000000..12ed6e0 --- /dev/null +++ b/tests/TestDatabaseGuard.php @@ -0,0 +1,29 @@ +service->getLocationAvailability(1); + Http::assertSentCount(1); + Http::assertSent(function ($request): bool { + $query = []; + parse_str(parse_url($request->url(), PHP_URL_QUERY) ?? '', $query); + + return parse_url($request->url(), PHP_URL_PATH) === '/api/application/locations/1' + && ($query['include'] ?? null) === 'nodes,servers'; + }); $this->assertSame(['memory' => 1024, 'cpu' => 50, 'disk' => 5120], $result['nodes'][0]['allocated']); $this->assertSame(['memory' => 7168, 'cpu' => 350, 'disk' => 46080], $result['nodes'][0]['available']); } diff --git a/tests/Unit/TestDatabaseGuardTest.php b/tests/Unit/TestDatabaseGuardTest.php new file mode 100644 index 0000000..18e721c --- /dev/null +++ b/tests/Unit/TestDatabaseGuardTest.php @@ -0,0 +1,43 @@ +assertNotFalse($temporaryFile); + + $database = $temporaryFile.'.sqlite'; + rename($temporaryFile, $database); + + try { + $this->assertFalse(TestDatabaseGuard::allows($database, 'sqlite', 'testing')); + } finally { + unlink($database); + } + } + + public function test_allows_disposable_sqlite_database_in_system_temp_directory(): void + { + $database = sys_get_temp_dir().DIRECTORY_SEPARATOR.'dynamic-pterodactyl-test-example.sqlite'; + + $this->assertTrue(TestDatabaseGuard::allows($database, 'sqlite', 'testing')); + } + + public function test_rejects_disposable_name_outside_system_temp_directory(): void + { + $database = dirname(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'dynamic-pterodactyl-test-example.sqlite'; + + $this->assertFalse(TestDatabaseGuard::allows($database, 'sqlite', 'testing')); + } + + public function test_rejects_empty_database_name_before_application_boot(): void + { + $this->assertFalse(TestDatabaseGuard::allows('', 'sqlite', 'testing')); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index dfe05b3..c3c14d8 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -19,17 +19,20 @@ dirname(__DIR__) . '/', ); +require __DIR__ . '/TestDatabaseGuard.php'; + // dp-13 guard: refuse to boot against a non-test database. $db = getenv('DB_DATABASE') ?: ($_ENV['DB_DATABASE'] ?? ''); $connection = getenv('DB_CONNECTION') ?: ($_ENV['DB_CONNECTION'] ?? ''); $appEnvironment = getenv('APP_ENV') ?: ($_ENV['APP_ENV'] ?? ''); -$isSqliteTestDatabase = $appEnvironment === 'testing' - && $connection === 'sqlite' - && ($db === ':memory:' || str_ends_with(strtolower($db), '.sqlite')); -if ($db !== 'paymenter_test' && $db !== '' && ! $isSqliteTestDatabase) { +if (! \Paymenter\Extensions\Others\DynamicPterodactyl\Tests\TestDatabaseGuard::allows( + $db, + $connection, + $appEnvironment, +)) { fwrite(STDERR, "ABORT: phpunit would run against DB_DATABASE='$db'. " - . "Expected 'paymenter_test' or a testing-only SQLite database. " + . "Expected 'paymenter_test', ':memory:', or a disposable dynamic-pterodactyl-test-*.sqlite file in the system temp directory. " . "See .sisyphus/notepads/dp-11-authorization-surface-reduction/incidents.md.\n"); exit(2); } From ae33b4653367194f43f5ee0401a32abb6f5da5f2 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 19:41:11 +1000 Subject: [PATCH 06/95] docs: reconcile wiki with batched location reads --- .../Admin API Endpoints.md | 2 +- .../Availability Endpoints.md | 4 +- .../Architecture Overview.md | 5 +- .../Companion Extension Pattern.md | 2 +- .../Cart Events and Listeners.md | 2 +- .../Event-Driven Architecture.md | 4 +- .../Payment and Service Events.md | 2 +- .../Real-Time Integration Strategy.md | 5 +- .../Node Selection Service.md | 7 ++- .../Reservation Service.md | 14 +++--- .../Resource Calculation Service.md | 2 +- .../Service Layer Design.md | 2 +- .../en/content/Core Services/Core Services.md | 2 +- .../Core Services/NodeSelectionService.md | 4 +- .../ResourceCalculationService.md | 15 +++--- .qoder/repowiki/en/content/Deployment.md | 4 +- .qoder/repowiki/en/content/Getting Started.md | 4 +- .qoder/repowiki/en/content/Testing.md | 8 ++-- .qoder/repowiki/en/content/Troubleshooting.md | 8 ++-- .../repowiki/en/meta/repowiki-metadata.json | 2 +- 02-SERVICES.md | 48 ++++++++----------- 08-ALGORITHMS.md | 2 +- 09-IMPLEMENTATION.md | 2 +- PROGRESS.md | 16 +++---- 24 files changed, 73 insertions(+), 93 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md b/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md index 5e6f354..97fd20b 100644 --- a/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md @@ -175,7 +175,7 @@ Notes: - [api.php:32-40](file://routes/api.php#L32-L40) - [AdminCapacityController.php:17-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) - [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) - [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) ### Reservation Management: GET /api/dynamic-pterodactyl/admin/reservations diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md index 2d71405..1bcf6d1 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md @@ -218,12 +218,12 @@ ForEachNode --> |No| ReturnData["Return {location_id, nodes[], max_available, to **Diagram sources** - [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-67) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) **Section sources** - [NodeSelectionService.php:78-86](file://Services/NodeSelectionService.php#L78-L86) - [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) ### Middleware and Security - Web session and authentication: diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index 8c5bd36..c4e3e69 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -296,8 +296,7 @@ participant Ctrl as "AvailabilityController" participant ResCalc as "ResourceCalculationService" participant Ptero as "Pterodactyl API" Ctrl->>ResCalc : getLocationAvailability(locationId) -ResCalc->>Ptero : GET /nodes?filter[location_id]=... -ResCalc->>Ptero : GET /nodes/{id}?include=servers +ResCalc->>Ptero : GET /locations/{id}?include=nodes,servers ResCalc->>ResCalc : buildNodeAvailabilityFromServers(...) ResCalc-->>Ctrl : {max_available, totals, allocated, nodes[]} ``` @@ -471,4 +470,4 @@ Common issues and where to look: ## Conclusion The Dynamic Pterodactyl extension integrates seamlessly with Paymenter’s built-in Pterodactyl integration through a companion extension pattern. Its event-driven architecture hooks into cart and invoice lifecycles to manage short-lived reservations backed by pessimistic database locking. The service-oriented design cleanly separates API concerns, business logic, and data models, while real-time API calls guarantee accurate availability. Strict reservation lifecycle states and admin-only exposure of node-level data further strengthen reliability and security. -[No sources needed since this section summarizes without analyzing specific files] \ No newline at end of file +[No sources needed since this section summarizes without analyzing specific files] diff --git a/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md b/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md index d0f63ec..5bdcab6 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md @@ -215,7 +215,7 @@ RSC-->>Controller : aggregated availability **Diagram sources** - [Services/ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [Services/ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [Services/ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) - [Services/ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) **Section sources** diff --git a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Cart Events and Listeners.md b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Cart Events and Listeners.md index c932d7d..3f3e1c1 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Cart Events and Listeners.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Cart Events and Listeners.md @@ -320,7 +320,7 @@ API integration: **Section sources** - [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) - [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) - [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) ### Data Model and Schema diff --git a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event-Driven Architecture.md b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event-Driven Architecture.md index 184b025..fb541f6 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event-Driven Architecture.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event-Driven Architecture.md @@ -345,12 +345,12 @@ G -- No --> I["Return false"] **Diagram sources** - [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) - [ResourceCalculationService.php:500-522](file://Services/ResourceCalculationService.php#L500-L522) **Section sources** - [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) - [ResourceCalculationService.php:500-522](file://Services/ResourceCalculationService.php#L500-L522) ### Audit Logging diff --git a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Payment and Service Events.md b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Payment and Service Events.md index 3e3d272..f5c9c43 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Payment and Service Events.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Payment and Service Events.md @@ -280,7 +280,7 @@ API interaction: **Section sources** - [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) - [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) ### AlertService: Shortfall Notifications diff --git a/.qoder/repowiki/en/content/Architecture Overview/Real-Time Integration Strategy.md b/.qoder/repowiki/en/content/Architecture Overview/Real-Time Integration Strategy.md index 2cbed0a..02ed419 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Real-Time Integration Strategy.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Real-Time Integration Strategy.md @@ -92,8 +92,7 @@ participant D as "Database" C->>R : GET /availability/{locationId} R->>A : getByLocation(locationId) A->>S : getLocationAvailability(locationId) -S->>P : GET /nodes (filtered by location) -S->>P : GET /nodes/{id}?include=servers +S->>P : GET /locations/{id}?include=nodes,servers S->>D : SUM pending reservations per node S-->>A : Location availability + max available A-->>C : Aggregate capacity response @@ -291,4 +290,4 @@ Verification steps: - [03-API.md:677-721](file://03-API.md#L677-L721) ## Conclusion -This extension integrates with Pterodactyl using a strict real-time strategy: no caching, direct API reads, and careful batching to balance accuracy and performance. Robust error handling ensures graceful degradation when the panel is unavailable, while throttling and timeouts protect both systems under load. Operational monitoring and logging provide visibility into API health and performance, enabling proactive management of capacity and reliability. \ No newline at end of file +This extension integrates with Pterodactyl using a strict real-time strategy: no caching, direct API reads, and careful batching to balance accuracy and performance. Robust error handling ensures graceful degradation when the panel is unavailable, while throttling and timeouts protect both systems under load. Operational monitoring and logging provide visibility into API health and performance, enabling proactive management of capacity and reliability. diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md index d8fba8f..96a84ee 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md @@ -90,8 +90,8 @@ C->>R : create(productId, locationId, resources) R->>D : BEGIN TRANSACTION + lockForUpdate(pending reservations) R->>N : selectBestNode(locationId, resources) N->>RC : getLocationAvailability(locationId) -RC->>P : GET /nodes, /nodes/{id}?include=servers -P-->>RC : node/server attributes +RC->>P : GET /locations/{id}?include=nodes,servers +P-->>RC : location, node, and server attributes RC->>D : SUM(pending reservations per node) RC-->>N : {nodes[], max_available} N-->>R : best node or null @@ -184,7 +184,6 @@ class ResourceCalculationService { +verifyAvailability(nodeId, requirements, excludeToken) bool -calculateNodeAvailability(node, excludeToken) array -fetchNodesInLocation(locationId) array --fetchServersOnNode(nodeId) array -getPendingReservations(nodeId, excludeToken) array } ``` @@ -321,4 +320,4 @@ Relevant behaviors: - [ResourceCalculationServiceTest.php:175-193](file://tests/Unit/ResourceCalculationServiceTest.php#L175-L193) ## Conclusion -NodeSelectionService implements a robust weighted best-fit algorithm that balances load distribution and avoids hotspots by prioritizing memory headroom, then disk, then CPU. It relies on ResourceCalculationService for real-time availability, ensuring decisions reflect the current cluster state. ReservationService orchestrates creation with strong concurrency controls, maintaining a strict reservation lifecycle. Together, these components provide reliable, scalable resource allocation across Pterodactyl nodes. \ No newline at end of file +NodeSelectionService implements a robust weighted best-fit algorithm that balances load distribution and avoids hotspots by prioritizing memory headroom, then disk, then CPU. It relies on ResourceCalculationService for real-time availability, ensuring decisions reflect the current cluster state. ReservationService orchestrates creation with strong concurrency controls, maintaining a strict reservation lifecycle. Together, these components provide reliable, scalable resource allocation across Pterodactyl nodes. diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Reservation Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Reservation Service.md index dd98851..bc2447a 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Reservation Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Reservation Service.md @@ -267,11 +267,9 @@ participant ResSvc as "ResourceCalculationService" participant Ptero as "Pterodactyl API" participant DB as "Database" Caller->>ResSvc : getLocationAvailability(location_id) -ResSvc->>Ptero : fetchNodesInLocation -Ptero-->>ResSvc : nodes -loop For each node -ResSvc->>Ptero : fetchServersOnNode -Ptero-->>ResSvc : servers +ResSvc->>Ptero : GET /locations/{id}?include=nodes,servers +Ptero-->>ResSvc : location with nodes and servers +loop For each included node ResSvc->>DB : getPendingReservations(node_id) DB-->>ResSvc : reserved resources ResSvc->>ResSvc : buildNodeAvailabilityFromServers @@ -281,13 +279,13 @@ ResSvc-->>Caller : locationData with nodes, max_available, totals **Diagram sources** - [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) - [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) **Section sources** - [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) - [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) - [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) ### Data Model and Migration Evolution @@ -501,4 +499,4 @@ Operational tips: ## Conclusion The ReservationService provides a robust, concurrency-safe mechanism for reserving Pterodactyl node resources during checkout. Its strict state machine, pessimistic locking, idempotency support, and integration with event-driven workflows ensure reliable capacity management. By coordinating with NodeSelectionService and ResourceCalculationService, it assigns optimal nodes and verifies availability at critical points. The removal of the 'released' state simplifies lifecycle semantics, focusing on pending, confirmed, expired, and cancelled states. Operational visibility through auditing and alerts helps maintain system health and responsiveness. -[No sources needed since this section summarizes without analyzing specific files] \ No newline at end of file +[No sources needed since this section summarizes without analyzing specific files] diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md index 1783340..b77aa71 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md @@ -140,7 +140,7 @@ LoopNodes --> |No| ReturnLoc["Return location data"] **Section sources** - [ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) - [ResourceCalculationService.php:146-214](file://Services/ResourceCalculationService.php#L146-L214) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) - [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) ### AvailabilityController diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md index 44c7e6a..3ed0163 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md @@ -141,7 +141,7 @@ Aggregate --> Return(["Return location data"]) **Diagram sources** - [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) - [ResourceCalculationService.php:146-152](file://Services/ResourceCalculationService.php#L146-L152) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) **Section sources** - [ResourceCalculationService.php:26-222](file://Services/ResourceCalculationService.php#L26-L222) diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index 52a658e..6f89f0e 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -162,7 +162,7 @@ Integration points: **Section sources** - [ResourceCalculationService.php:23-222](file://Services/ResourceCalculationService.php#L23-L222) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) - [ResourceCalculationService.php:302-384](file://Services/ResourceCalculationService.php#L302-L384) - [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) diff --git a/.qoder/repowiki/en/content/Core Services/NodeSelectionService.md b/.qoder/repowiki/en/content/Core Services/NodeSelectionService.md index 136dbc1..3152dfc 100644 --- a/.qoder/repowiki/en/content/Core Services/NodeSelectionService.md +++ b/.qoder/repowiki/en/content/Core Services/NodeSelectionService.md @@ -102,7 +102,7 @@ NSS-->>Caller : best node or null **Diagram sources** - [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) - [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) ## Detailed Component Analysis @@ -185,7 +185,7 @@ Error handling and resilience: **Section sources** - [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) - [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) - [ResourceCalculationServiceTest.php:53-139](file://tests/Unit/ResourceCalculationServiceTest.php#L53-L139) diff --git a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md index afec7ae..95685e9 100644 --- a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md +++ b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md @@ -89,11 +89,9 @@ participant HTTP as "HTTP Client" participant Ptero as "Pterodactyl API" participant DB as "Local DB" Caller->>RCS : getLocationAvailability(locationId[, token]) -RCS->>HTTP : GET /nodes?filter[location_id] -HTTP-->>RCS : Nodes list -loop per node -RCS->>HTTP : GET /nodes/{id}?include=servers -HTTP-->>RCS : Node + servers +RCS->>HTTP : GET /locations/{id}?include=nodes,servers +HTTP-->>RCS : Location with nodes and servers +loop per included node RCS->>DB : SUM(pending reservations for node) DB-->>RCS : Reserved totals RCS->>RCS : Compute effective totals and available @@ -150,7 +148,7 @@ Usage pattern example: - [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) - [ResourceCalculationService.php:146-152](file://Services/ResourceCalculationService.php#L146-L152) - [ResourceCalculationService.php:226-245](file://Services/ResourceCalculationService.php#L226-L245) -- [ResourceCalculationService.php:247-289](file://Services/ResourceCalculationService.php#L247-L289) +- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) - [ResourceCalculationService.php:500-522](file://Services/ResourceCalculationService.php#L500-L522) ### Method: buildClusterSnapshot() @@ -252,7 +250,6 @@ class ResourceCalculationService { -getPendingReservations(nodeId, excludeReservationToken) array -getPendingReservationsForNodes(nodeIds) array -fetchNodesInLocation(locationId) array --fetchServersOnNode(nodeId) array -buildNodeAvailabilityFromServers(node, servers, pendingReservations) array -fetchAllLocations() array -fetchClusterNodes() array @@ -316,7 +313,7 @@ External integrations: ## Performance Considerations - No caching: Real-time queries avoid staleness and overselling risks. -- Batched API calls: buildClusterSnapshot() uses include=servers and paginated endpoints to minimize round trips while maintaining accuracy. +- Batched API calls: getLocationAvailability() reads a location with include=nodes,servers in one request; buildClusterSnapshot() uses include=servers and paginated endpoints. - Timeouts and retries: - Default per-call timeout and connectTimeout protect against slow or hanging connections. - Retry only on transient connection errors; 429 and 5xx do not retry to respect upstream signals. @@ -358,4 +355,4 @@ Operational tips: - [api.php:17-25](file://routes/api.php#L17-L25) ## Conclusion -ResourceCalculationService provides accurate, real-time availability by querying Pterodactyl and accounting for pending reservations. Its design prioritizes correctness over speed: no caching, batched API calls, and robust error handling. Together with ReservationService and NodeSelectionService, it ensures that customers are offered realistic options and that the system prevents overselling throughout the checkout flow. \ No newline at end of file +ResourceCalculationService provides accurate, real-time availability by querying Pterodactyl and accounting for pending reservations. Its design prioritizes correctness over speed: no caching, batched API calls, and robust error handling. Together with ReservationService and NodeSelectionService, it ensures that customers are offered realistic options and that the system prevents overselling throughout the checkout flow. diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index bac39f0..3c9b177 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -137,7 +137,7 @@ Important notes: ### Environment Configuration Requirements Configure the following settings in the extension configuration: - pterodactyl_url: Full URL to your Pterodactyl panel. -- pterodactyl_api_key: Application API key from Pterodactyl admin panel. +- pterodactyl_api_key: Application API key from Pterodactyl admin panel with read access to Locations, Nodes, and Servers. - reservation_ttl: Minutes to hold reservations during checkout (default 15). Operational requirements: @@ -456,4 +456,4 @@ Deploying the Dynamic Pterodactyl extension requires careful configuration of Pt - Ensure tests are run against a dedicated test database to avoid polluting shared stores. **Section sources** -- [phpunit.xml:28-41](file://phpunit.xml#L28-L41) \ No newline at end of file +- [phpunit.xml:28-41](file://phpunit.xml#L28-L41) diff --git a/.qoder/repowiki/en/content/Getting Started.md b/.qoder/repowiki/en/content/Getting Started.md index 9ba2f6d..33b6c8e 100644 --- a/.qoder/repowiki/en/content/Getting Started.md +++ b/.qoder/repowiki/en/content/Getting Started.md @@ -229,7 +229,7 @@ SliderCfg["SliderConfigReaderService"] --> ConfigOpt["ConfigOption (dynamic_slid ## Troubleshooting Guide Common setup issues and resolutions: -- Missing Pterodactyl credentials: Ensure panel URL and API key are set in extension settings. Without them, availability checks and reservations cannot succeed. +- Missing Pterodactyl credentials: Ensure the panel URL and an application API key with Locations, Nodes, and Servers read access are set in extension settings. Without all three permissions, availability checks and reservations cannot succeed. - No sliders appearing: Use the Setup Wizard to create dynamic_slider options for the product. Verify the product has at least one slider enabled. - Availability shows zero capacity: Confirm Pterodactyl nodes have headroom for the requested resources. Check the availability endpoint for the selected location. - Reservation not created on cart add: Ensure the product has dynamic_slider options and a location is selected. Errors are logged but do not block cart operations. @@ -274,4 +274,4 @@ The Dynamic Pterodactyl extension enhances your Pterodactyl products with dynami - GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes **Section sources** -- [routes/api.php:17-40](file://routes/api.php#L17-L40) \ No newline at end of file +- [routes/api.php:17-40](file://routes/api.php#L17-L40) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 924b0bb..db5cc12 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -189,10 +189,8 @@ participant RCS as "ResourceCalculationService" participant H as "Http Client" participant DB as "Database" T->>RCS : getLocationAvailability(locationId, excludeToken?) -RCS->>H : GET /api/application/nodes?filter[location_id]=... -H-->>RCS : Nodes payload -RCS->>H : GET /api/application/nodes/{id}?include=servers -H-->>RCS : Servers payload +RCS->>H : GET /api/application/locations/{id}?include=nodes,servers +H-->>RCS : Location payload with nodes and servers RCS->>DB : Sum pending reservations by node DB-->>RCS : Reserved totals RCS-->>T : Availability with max_available and totals @@ -460,4 +458,4 @@ The test suite provides robust coverage across service logic, API endpoints, and - Identify slow tests by running subsets and comparing durations. - Reduce DB operations by minimizing fixture size and using in-memory databases where possible. -[No sources needed since this section provides general guidance] \ No newline at end of file +[No sources needed since this section provides general guidance] diff --git a/.qoder/repowiki/en/content/Troubleshooting.md b/.qoder/repowiki/en/content/Troubleshooting.md index 5953abc..c566124 100644 --- a/.qoder/repowiki/en/content/Troubleshooting.md +++ b/.qoder/repowiki/en/content/Troubleshooting.md @@ -120,7 +120,7 @@ Symptoms: - Error logs show connection exceptions or HTTP error codes. Root causes: -- Invalid or missing Pterodactyl URL or API key in extension settings. +- Invalid or missing Pterodactyl URL or application API key, or missing read access to Locations, Nodes, or Servers. - Network connectivity issues or firewall restrictions. - Rate limiting (HTTP 429) from Pterodactyl. - Non-JSON or malformed responses. @@ -131,7 +131,7 @@ Diagnostics: - Check throttling middleware on routes to ensure requests are not being rejected due to excessive frequency. Resolution steps: -- Verify extension settings contain a valid panel URL and application API key. +- Verify extension settings contain a valid panel URL and an application API key with Locations, Nodes, and Servers read access. - Confirm network access to the Pterodactyl panel host and port. - If encountering 429, reduce request frequency or adjust client retry/backoff behavior. - Review server logs for detailed error context when non-JSON payloads occur. @@ -358,7 +358,7 @@ Diagnostics: ### Authentication Failures Steps: -- Confirm the application API key has sufficient permissions in Pterodactyl. +- Confirm the application API key has read access to Locations, Nodes, and Servers in Pterodactyl. - Verify Authorization header usage in internal calls. - Review logs for 4xx errors indicating invalid credentials. @@ -528,4 +528,4 @@ This guide consolidates diagnosis and resolution steps for common issues in the - [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) - [DynamicPterodactyl.php:116-126](file://DynamicPterodactyl.php#L116-L126) - [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) \ No newline at end of file +- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index ac050db..ea8bb38 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-86","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"247-289","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"452-498","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted:qkTEybd9tQzuDstX5IzR1CXs/trJv2Qp8kaORmGdEsjOxLytJAqUuHjP06XJn9y+iXOi9CHh5MccEBo3czEUCbEI3xi3jI2FX0U5Hb1shR6LDZa4SKyGHNVixTBNySA00Nc7Lz+raBGyJ9EnF9lGDKWB1J0M+K73LX1rF7N3R69cErBcAhuvCBd69rsyUTTKSXgEpXu6a6WBUCYLToWdn12p9VWVvjTtcSe6lRUrzgs90/zIfQVq9RYyW/9LbF/T1JjqYM0NGvS+uZhPFi3p2U9QVLIuGWoSFWeMUW7i/mctoN1NLGsU3TIOSauX990uB8YSEC+j3CLEU0RFn/c5OsWoAXtfngYrjb4AGHl2NEDSkwlciQRkxkMYxFEZyYcHT8Gpy9mvFvx8bbUg0Pz6UsIgth+Wt8ksCwhqUfDKRSDFIXTTfvORPKTzfkyLwlHIqFcgDPVkG6zJI8I05IjUlXG5jKJQFuSvTIn3yJqmp7ZhvKQoeYLzB31v5M+ZOkDLxB20IFzyEJJaajhK2ne42xddTRga+uACLExPlaXQ2RJgP7aEh4BxFflfEZTJ34EAFDODWNpg+cS/h15EWTsUaCG4uC1kiMBrOd2ozslPb/B4Edh29LEeX6942jquAGPtDbui9o80AA5R7YrXIWL0yCvKlGIvVQkiQRQKUdaVYNvT3BlqJ9Ka2WMvnXeD93o7uFgQDqkb92et5LlCLAyZL2hhn/HVQ2au4V4WnXgjVYGwqLpihYFplV2o6Ul5PDnwJGD69mAO7aSGG4TBaz1vo7thcxfYaEN8buhL/QRsNVzwqTeN25dxKdYd+zBxU36BMRYfjftV5aUHpmuuyJJkM5VRKQ6BjVw6woeWtQG8FgIoVUuFHpxorMTccI2C1mpkmzgRNMXQ85uoPlKkLHfbtEhYmKBBI5pISQM9VE6ya4qmYS3ZcA4Gby+GuS+2myO7b+pIgX6Gq8Edw5WSPn2Ei//99pnHyVX5UPawG98jbNRlrQs2TtcrBTUT98D4BYcMA+ktxGDZix3F4RcLx5/elIhe124f8f7S+X8phIq7uGTw+ZxP8gQsdLdGaOoF3tin+ZOK0iHk3oIa+E7zaPMUeNmQcixZRtKa4oIeo6dr4zHVltAOiLtV52OQDsPPCU8HwUO9GFXeTYlUMXhErji/Bg7K2iw712B/4pQW0+0M4atRKpXUCf0AstnGoCz8LlV+hEsMY8AS+k7jCk4TW4pv758c4geH+8hGXMLUSEdVybYs2P4Vk4c8nAaIEP6jWukiDhIps/dyb8RExWg5BKcfGJZXTWi3TBQKnGIqc1JgXXJUAOfGwP87PHb9WxxWsvl+13KF6/JUV2RuX8NWSAmST2z9I5whzQnfem7CCc2i5yO6yqpJbPOt+hpYlqFYp/yd6gkodn84E4+o9G2F9NamhIk1rCcqX0YoYhYX3he3rU49QIUaNev/DsEKQc3s+K3yH3L969uk8nvcFIDEREP3Ke/07RicsySihmrgxJ98Ld4lr2V25uD69/exLybGUdn2dDcVBUfI6jWrwipyYCInTV+f2WDOy/ki/Kv/G4WbDZhIXn006l1s0GcFML1GXUTxXmJY0ku4dOxbpkSooJ7fw4n3y6hHWfG8HpJT6bxgFd00CbYoe/b0gzXvAaWW8vpkN1sYSWr1kqeYKUzdSIW57T/K/LOKTHdgZA+L0R1R8CEvL/ecL3GkHaFg+gEYwMpDWhf5rCtDxKebVIATR9aw07hbWczXdZwkDXJlVd5V5vdgORzxjfzO/OFC44ruOlxQSlTZLyulYQFp9dHxHnHSP0L24zQXaZKtefy8cnmOapkooReZ+wZRWiAb7fxmo9D1teGxlOU66NKDFzhuXbd+HpEiPqGRF9y08wPLPou9goHOa/JMQmjgWBUVuQuDbR+a74MSWaZCcIwojBJ/uBzCR1IFP2H+BJDuKSrdeLDMuW5EJu5KRZ0B7R+zFnwOxiZ9EYJTIFO4DXNRb9ZL4JZaZJDqwUUgBM8pWHec/4cM+iRi7hh+rkEMQRAMyGpem2L+oSpr2mWWzpe8wQhlaZeVV2sbybXQ/c1TEtK34eA4FlFqimXo12UKrmimZi1mkAyuF98LXH1wCLNXeJVLWZOMKrSl17JGy+Rgsx9dEnAmdAOt/ePsBXXphzaiSY+6GMqmtIINfcgpsvFLf7VhdP0yeZ+kkaT7kJ6yYu+EvJqw32jYBjw3cBy03f0wLMX/dMHo6VPVsef8AiKqBBoTxb2uWBbY31nXY9EQgRoYajhQYdmKkqEJWTkgXQTwQDHnUdrR69KAqK1wYfDX38GDERT9ibC6fXsUZGq+QgGm8VZHTsFTnVWZUi9EUCA1oH4p8NtjCRKQE1dUmCiF/sMRKwCgiHZ+WmKV4ixhHV51T5RAHQ1fkcqc+hPFcd9uEqHPrwvlORQ9jh5rDbFRNCijsw17TiHm3NlZIZ6TOhCPiPO7135f1/4QfMvhj8NftvFreT17bU7G6ZhUQAvh6EcXhWZ2LDqZR6Buji6hu1u+6WgCFFNo+TSLl+h0xhKxqKlA0H4FQImLcJdXn4MBTrmQhqMe5H1iyxIN8bhT42s42eS/2IJqrvjiLVVNiU9DbRlYBe5TsLfZuC9GQsWYHdHB2KAAAceRlYBlwnnnVPexQl67P/G9sMfPJkJP7aduEQc+ikG8og1weDdx5GYauM8O/D1cxi8/7lTsEtDIGXuCC5OOHBs7utoXRrzgtS/D2kgNytqDqSaHVKaNy8NDlNMYbjHbsr4ffxNCRN6Pv2NPi1RODmwAvliw6D7KLOfoqACJKyBasvMnWyR24InlREQefIeRrWJ37pr9Vq55Q3FhvhZAc8rPO+f3plstLlPFQuqz9RWznCe1tPE0niOz5NHBZI9lhIv8cOJgZRzQJnMNAIPVderB7zfqLtTAiq8aipiVreV2y2vrLz0b9lyC8yWPsQK3aseiv9yw6i9ehl4z/sHroeApfLHdyEscUVNJXOvapP2qTfZ9jk4hocuqydv/duI2D65jyGlk6QuIPkjjMcJ8zaFur7eFq177IRSKIy0XT5XPXjUFSsnXp0ChOnfbgKyNvD71SvzQT7GwZI6hAH67jxNZKymIWPsLwAFOl+M5XOs8X9EnYbxKTReoFUvgerc0IprGMeJ16tH14Yd0i/HHak13ShbBkqSOrBhhWBRCCGt73qsgdMPKqQaZAihM6hzVtV0uacQePDcxX005Zjorr5rGsmt6BTBWli/TnwDZB3Ttch1RUd2LJTCCIf05zCDZAtrx3zbm5Zoti5VWjScQta3sIvXlpHyQkCjB2varsGqAsAM6xbX6bHqsYlZCwlk1uP/VKVdUU65hWydtK0mJCHJsMV/H8ph35q74Pd6y7yvcwg6oKZCuQCA+Cd9TiyAc3Nt+wXdMFlMxobEz1J0fL8o1BKpsKI1yNn3xff0/UITO4WG/FJ3ryJ1ROrErGmcxjYSgvBsYrkhIUJRMx67aSnqHC3oQ7SWeFeJrTuyyrHD99crFg1wWW/Ny7Jkko38NzNnHHArluH3t678lUA+iwYkFUmGoEtS4GEav6aW5hU2cvXiL3Sgog1Eht3LcHBLRR5Bf6n1QOINMP3Japm34G7BaoZ5TNwpgoVoJL4/vUu1ncx7WYfgP8KlUhUAWtI6NFt/vMxjZ9vhCM4Pgn6dQLn/vpc6aYRsyEZChXu0wLqM9O9zLbAQ8qEOA0e42gpKoXjDUYBnNFu0Z5xjiaRu4B0LT64hpm/n8NvjzD3dL/9wv6xCTKdt6T7PmeIUrpxi1OcprTww1m+Op0qyeOzKRfWHQl9S3dREaZ4AXqDFETvCYFD/VJ3U5pXRr93uIH89E9eoGaZQbr31j5m5aYERY2ZXF99fhxPSyd4rranhUy7m67NgGGaNgdqnH/9rR1NPpFb1xUwymj4NoSg+innBL7DfFKsWMHumXC3b+C5jvg3WudMgI0+ODGO6MoYDiERrxIidOP5q8ZN4Jfts8pGffE5/sd8zNMP36qD4t8nF/pskZsgdOVcsUzPmuB86IFlV9bD4eC/RdmJS/lHgmgQ4eTpFRNADPwqz9vkoPtQurxMYLqnrF7LElAIGXC0U6k/oyDz7SKDz27N5B7ryjSs0IVLV2Gy7ZncOKbEyj9CPNXy9vR8rAIDrFLa1QNw+FwYgPu+RoyTDJ9S55NDjpALze3Si28hXfGIoA0HSvM4+r1S8EfRrQmWs1o+qBh1pDKt9hnFpqLjq08Kz/UarsuU/dKAxkzP6FSPHWRYY3YCd6U4lJq9LL12d9FcrgYIz72opWVgWq5BNezdmM5foqsAFgDujPmGbB6YdL7kTyt0rcxMBkjlP56SnD8hLaBG7oTkf4GCzquMcMhaFf1pklIKJi90kufl9CDN0eYHjnF+AzeLf1p/Ruq0IehmliQXA1No4mXjiA2qU1BnmzqTNCyAWN32S+fAkeEfSd+AdD4sMJSSLUhNwaoTQr3qSp9Q0qW2KZGchDCBDXE4mTCyxPNDnHCSvmq+ayDviJacujoKbZNnuuZjgJ5eitj0nuD0S7jD/URAoUq8UAEzo1qq5eziSUw6z38U0v97ZaU0hohyYSgjBAv+umzJOrnY+Wu7SVW/53kYb8GpMhwkgdvQRKZcBEUuR8o2LmYWilmZpKyH08poYLj41wtsUQaVqhgItvECi6G1V1MRg9BzvvHSGxU3jglpZUgzv4dhYrUxabLiVdFRLyAtZ+nx5YSidIxtStPEnWKIR27k0BIsYLP0yO7npcBkx9v7urwM1oh8q6o9mtPT140KgBqUPMRKujN1Qiw0kQ1BM6TddIsUWMS4Jr6oH//jZqDqOM1BgFjEzXhdWWTnwHe8Y1x35EGBfYupFepa8/H/6iB8HUnbLcEg0sS1Hla0OHtaut4N6i/rJNlfBAYjK1tyDv/cwm/bEClj0JzLRWKjf1Ae/1b0LYWIDReal8V5YqrdkB766d1yx+xZ+oU0c2wAn4ij+Do6RRtrV4lTFGs/PNS9CpiYS9yt6xXt+2rFuKuWrDxwLl5krZDJKTvpO0s9aF7jjljsDfcaKJQQTlTkL0h1z/KZxm41bg+KcbsyptkUR/8Xti/fBFOUSBOUd2E0ppEA8/r2pxLlIYaIQb4dYsI3bqvONiFviW9qExQQZ2RYJ9dLDykZiujhQ2nEJQOaCc7e+NViygsPHE0NTb24LIPbnAQX1W1PCt8RtndICZAJI60dVMni+ctjifd/hwY0Llgl7d866veLh6q/YZn2f2qBr6ms+ar6mIrT0zapYhNG+hLWaXxThodnNG02y4Ifd9wFSEkMOqaeMXxCBRquJ8QoH9wSd6nYO3VDChhkPpqdATuWj5/hI5SUtcmDOKTe9FtpP+sSIII8thsMraMi34XovbHYPFdAwrSy7P46GbtrZKTG4gKr3ZtlGIMFlYEPeTPL322mNwjrj92Xtiv99blZVyVShhhNHlHvcFPjXvVWiI3iNMcdDs6Q4ZRSjkLTxVaZcFHL7S6/fj/TeKcISQMVvW/+80GI7791wFpgzGt2UfMHcCakrxgxpldcwlqSTVsMDRMkWaQQzsqaODqL9IZoMYyGJweawPyIFbCanAUfBpoJJUHrPCPVTzsG+5TupSkaxAqSmonKiCcqUA4Ra7rc7B6H67hFyaqzDcQ0HnObKpJp9Z47+70k1bqqE5DzVn9jE/pXNBplDGe2EN1ElmWGZ7ZFl5RSZeNxhCZ90+qOFe0RfYZyk0g7qi0KDnSmIttTqBNXzyktDJhs8cqPvs17y38gAjI9Q2RtR4ShU++7m/id9sSjv3xAHhawuUdS9Pgj+OO554Xezol7Wdn0kx+oTnVEZsOUDtV+8dx9M1X+b3yhEONQZQnpkLzz5trviuVmzgLKxgopFB/Hmh1d+E4KOHkV/SLfy+a1bz2FXqUzu9fX+oRKLKmJJD5Y4sp+/gJSH68oriVKGq+hvF4F/RBmkKMXwE8KTw1LUFl7dMvkMuAKoNnklEyyyVdKit0vtj00CqZhG660jA+5z41hadJqUZ+lK+ITqJjvUrjmKOzQ0q/CIIJETrpCfkjXZmqb4Ebz47DJ16umz/a0IWN/tiFyuwoxzvdGEMGKQ7o8Pd8BciB3LBnFUoHMtR0yW0jxctOzrftPZ/vh0JSHOp6ux72Vh9AZgi5TphCRvcpKlba/I0IyYzkevNboCRgYQP+Ap5rj+93nXiGWTfRk2mSpyLral3GHzhAMgl972OIpcT5/Jm3DX9Rt5xScquys2wJ2dVY8lhiPPr8zMvy0frQL7I5056M0eQjoInwws4fIZtBfEYy+ycrVnZDK6EIc1FdGItERZL7gIhphZ4dcYXtj8cRF6l2PlQ504mB2w/WVH6zE9naxlibeNF1JpvRZ5pKl2Jna35M+axy4dgC7rhji2OIE6pjCle8ZW5yezeopFZ+gelvlQrNqVR8pA6lGoPp/VixuWxbDG0MqAYPN+4+UqdXGvEF5VGcjWCJwfE31XaLZNL1XKfqzBuEAD6R6SuRb4ik9jhKDmCOvYyF2y2jxovEJKGv2qQ04poITEbD9Z/VoGI6qH+Ldfx/pHSxxYj8QfadppQBhfWROJ4HaW65WXESK7kQnLKzIcRk97zLXiBUAfDnoROqbd+VzlfnXGEogSfskcNcyn40WdRAZ9EkO3qWeT8L7eGa70tx0EDmSfkv4EUZhKMKbJwsAyedmc/tmVQyk2CVQCzgBMW5AdHgfkaHRTqiPuRpkSnVVCfi5yUcfdgKeU5eho1iFzrBJ5FWc4LtiU88uOOFewUSqski12Z7xAZDF9QH4eDOcWEIRwy8nzflI0C18Hjz/AVBfeKxfuVf56MJD1M9b5ZyKgXF2uv+2rtOC87aqaGDKkmG36eWMjUpj55xm0OrxhnFYb4io1c7Ar9GHOTCp5d9T8b8AlmDghYu9Q4BS9eu1fC5mk2qntj0gbtITw9yrm94mnFR3epFBM5VimXsIKyfkN6vaxi/VYxLzs/m8P2/iMz5YhDPSpEoE6dtGi+RYFQoGfmf4Kp51MvhxKpBWzIKUZ4oVo3bSR/xTtA8g7m2Cu9TmGyGzoRsGZVWPwenitAOr8BK1F2gZIetevGghmmjb+dsTllfsZSkAVO+a/QWVxiylobFRc/EGg1uQzlL5YM9+6L/vwXg6zBN9kGoGj7BzOCNk1aNyPkub8+YZrb16Nj9GZcHqGJWRlAqG/XekCaEDdi/tUuwHPCTvJpmceD04ErapLgvVI42e6zgSXMnb4xQ8znJCFT/H85Air3ZAMw36GLTdxZbw+csNjB7990zjLDB1/gslSZrLuBFvtO2ciWE7AqYJd4YUlhLF4iLpy5W4Sw50GjAW444Fgp6oVJnQlL0tV8APr2xbLWp9Eo40IOgvMNVPwLP/v39jsXjKT+VrFgPBaEYyxNIKtx8MAUPhCaPKzpEL58BAo4j14o00Ma4zDTGbFWPXFfbTMBZtDjBD7n6z/GJZUFz61giQOlLsQ0APQW//bMxmh8FgqEujhae7IEDDgm98plwNfmKQKAv+nZB6h9iie1nTVLTm5P4ZSw+v3VpETskl9Bq8RT65DPNdkO8pqMBj8J6Xm51FlrR0ErRv/ynI11twA390S1F5cLg+OLAOx271Of6n2wxWTJG/peXEcAVfFaXXlsmvARiKku8WQu3W/38Uulrk1fg3setfivWSWv2nJvb6NLQyqX1aN5B4vMtm3Sx4oi+QCmHpKr4+n92EdLsHfZJa4Ldm49Lqk6CkD6kncpzbtAjIRTVUXcC/P5ujAwgZPyCyhiwkRJnc1ZBJmbF8JianRsBqhnzXpUBlsOObVOdyjLn3rFDaigXy90uf3vyrSJP1LBqN6DjEKFm3qQXpgmEIqfjLN1upGeb3/PrJV6ylEFwbsPv03ZZvlHP6RLo2fOotcZBh/E+EVPvXv5bzjYVWfDbV3wf6qnr5ZX0muxzBkYOnVp2m0mDA5cgkhI8pY8vXhQvMRBPQpqe3OPJmr1HySivFsIWnHbpSKfTYY9BJYLlEP7cQWwboEHAeXdMpmTx1IOUnJAO59nOml+xyOCSwelJo2W/nCTPuEEGkBHLjpogzvEBe7DZ8j4CjYynzKdd8UEVuXCkKvQhDC6HGQhd56b1uxmxh+Aq/w07/nYu1Y60vEk0Mbi2s0Jo5PpcOcG3ZmRXGJf+1csDOpm4wCi+iF84wBewgxdIegpjPTRopBHEPYH1MSRHiBliqdxf9gipweLAX6yLOk/N7H/gqXarYkCdZXxEjpoZauMfawkM7Q/wSjTKV/vi0en76dmnTHOQzAUjGfBEdm3DtJRZd9XNP27syr6nu2mefGeB+q9sHnNOIMkn8+ZBd5aQdVZT/HvT52vWseAb7488OnqKWAXinkPMoOpx151M5Dwh4n5aMVSqD8+cwTnrSlcuBO+tFrxdDhpCjOY4HRq3Bipo8A88g5OJPBxTCX4Ms9FSH21e/YFA14rMyjYfBMSz3rCdSYp1Ni/U4JT4mU5wGxE0/4djSDcJVd69oE4XKftnVrZQuxz1xKObEy3VSf0/4VN+GtRu9PClRTv63n1vWX4R52q3ibpWD1gSnCxUnMGcovNWSM3+syP8G5yZFHgH8sVuthC1LvODHAa1r1w1gzLAWMMQlYzXo0CRruV6bNDGlcp6KZkgbmOZDX1DWXkrz0r1sTmjTSM13SBuBW4EaNJFyvoV5LLW/yNcUDzhhwysPeGF5df01d+svZEAgHYA8Ogf2b0U7Twj3zx8IqyFfuk+q8TA4trDvU5z/fDNnZazo5r526djNB9+vNMRuxziw0qf7cZuJVMHR5+ek9t5JprtGyXisj7a0LNadiSdFxx5hyMW1SStaM64Aj5w9+m1wGu8Mx5eZ4YX6tXpnc6II3+8SQY20Ui9W8niZVOpr4ybqsaaHVGW9Qzxm6UJwSjtgOcWVb6RsO3i6ymooRxQbpZv39tLrxc42g4Vn8hb6x1i3ukKrvtMUvidfbdR15kWYyV1O5PcPXZ3UnMI5fJS8NhsFLE60UNzIga7p36e4W3b+hKghoKnk6JfRtSn7W2dtJgD+pJPhKOxuOLv+fLBT5FwIOHtDzSrdfQrIeiw1FAOmemg6VLbIGiZY86LzBOGzget0EKnLBmMEZip7FK9xIPno1ek3h+EQhg+aDtm//h/VR8Zaz5H2ls6UThDjbVVBw6ffW3Nl71KdgGDk+/D1pvVIc6yfpAgfqt2IYSIjiwJAlvqWZWxR/DkZQUfO0Tjx7fbWp7dssuOrIwo3KQALWFLOBCEljuas4Sw15z2kEQgwquReMhCByUT8vADZMeN1VzAt6X73/ZByCwoVx5rxFjuZkfpXOoxeSCBJtTBCbDlmKHAEb35Fo1yDcQDSk5TlcgrFG12VRpLkHOlZ+fCRn/T49V+TRF0MPlTh2yuJaAl0K93cs1uqqRATX0KsF7XdQOU9FMx8gr7YrImpvgUCheB5XJR1viAxxKCQpaAPpG8SyM1eAbTsNmWsDXz0o9b1h+iz0Pndozebu4NtJLqSXpXCVSsfLlbAaCdHvQ/hb7BEGKf63aL27oNfROm8x35ul6mLX3JWheWr1oPh/KwLgJhOlMPUEDTDMzSp9XpJksZuB4ricLei7rRIn5YE/NWaiswBb5oknS4hicl8YYYRzryUqOdC/7z3GTLXpmFP9eSolf8/Rzt5KNtJQWQK8SoiAbu4e4/ScgM1wzUaNnMNQ0RV4wFAwZ4vvkFNDzVAwpJqWIPaA/MF2cGJOfxA11Ssuxd/2gHXF65fJ1y1sOi10yNWjdnZjjnf8KEdd8ApKjNpMzD2WayEQXzmXXKQ5Ym9FlJb1oIsSJt9Fv2YauH0FlsSO0IWOu7iMPJ/Z0mo5ka31AtBJh9c1gtUxm2xo3t1qhMGnopFozQqeZgiSufSQ3pgrGrUqjwzCsmRZ4qtSOaCu1eDSgR2+DTJ3kSjU9IkiII0G0vFvR0bwL7nOFWBHzs8LT6eQic/CCMCJXuxvvwTknfgrDYIj29BMK5Q/PoMO7JMlG4mfMQ/65QkdmKvVVdmJYl8d6kHjawEtS0JsTwaPFhwNQcXXR4QBFtfZq7hZTyAl0VJ641n3FdiK8YjUJRhRVErBbY8vpSW8Cw5DXTo6rVtbmDM3GHhGWL/EQmL4yVLnmqJloHiCH9lgCZ2spd6WdTbg/G8lS81eFiE3AdnUvL8nOxCVE1cm886d2z5rJL7xXOBfhXiU535UD1FTXOt9IJAGFOrz3q7a7QBcN0mXqjabPSLUzao7SLxzzQ3N5BBtY9E5A6F/JOeJ8k1azGBsbBmHX3gX009gjdyh2FEi4isGWUYmq/ppVDOKRM9TrYBIusyuL1uJnvliLE41KvUnj9cVSGu6Y+LhOShU0oIZzNqlLz1drq9WtJ0pNOBHHcDBUZIHKWkvQu2Kj08LAVuKoqCUTB+bbFSubHE8+P+LqHhU1Efi+bofZdd8IImHxlzSay2TwOJmYr/vg1ttPsxY6QK2cUYrisuDe9flpa6aZ1TDUghwOD3SrGayV0EtJznsqVdhFFrMhyJVUZNqnu/Dacu5QExvHCzFWycNKt5DhsDafNS4OhLlgZofPhh0ORCnb31pkhnfZH2ViomqngfDk3HZYuwW4eKaQuzAskCW9lIk+PGnnNa4MgKye2sy+Bth5Eyn2Y0CHD3wtChNaro+GGoZpaiOyv5qbJLbMO1FfBeD7EGb4VXFQF4VBxnnGV1OFZwDKoa7w7L//On/9Nq4eFY8IJABXL/JWxphpALlAImWxSgoAg837PbDY9dbowRSrVQjhJZUM09BEL2FR+P3kwPwmzE3ReioFgvcAZtTcjzFZs2UHJSk6Mcphkd6ZCr5HIcqgC6GXPa4Aqesw89Uxz9DZfpR7PJkygyZQzn+nGFe9UDOfyqfNF4MxitwhtdniTtmpFTc2JmTNNGNe7IOzYE9kwB52RtLgi79orjTDW5DZ5TnJIqM3sbis0VBgUGXb5JY7oVpXPDmp5XByCkb2voab6P4uFhT8C7FmtsJVQyPRlddFGilUPX+V+n+ANkBMUhuMdowRyKwSxfaNsDVSgdTuGpOw0N2qr8kDOM3NDaCSUXNLoaxxW0NPdO7C7gFI4vcdYhiHy5lLmxuJD62giIjMqQOxH5cefdO8+eiMemWEBA8NQ83eQD+SCHuzLgo7LoIvZmzskylMbYFIwEIzAcy99HjGicmpxKzHFHyN+CRurnuNxaaMqx6/iNmvXjrftA21yI9Yq9T3Yip/33ksWdy3c7IGe+PI0WYExvJ9c/lBmMd6SGu8mKYF/pMxVOATbR5+xtU9EPvTKfOM7TmG9K0faNj7RxdZdua6eui6PekC3iqcWyGt3EGe5j/do2IYobTVDKKhnMZnSgEOmx1rTBo2KKbY4mYB+RtNvMhRJW4StmcRz8tPcGwZbrgTCjL+D6d5oxRiiZo29zSKfQ/yxmLwBPZi4v6LgZGpCMGcUqSSH96k7eBtSoifW31yPc40wPMNsgRBozhjEagoHnrFGA8uxx1turvhD+04CaMdCQGjZ6icqM9PZrL+N0vjxFN7feMPCHySBixzE/k0gwDf7hpMwZnkWoBwF16bK8pNYxmME9DrFDMG1ZVELOxH1PqMzOqDTB0uv/9si0Y/5PfxIk1H0BbpxVOacW9gDfuwaxVnRYlTl6JDYgDqDuXSAokO8ldVhABFE5RQdKb1J4nx2I7VDmS811kQTLZlZZ6jdvLDKKVq/yvnk4j2rXW6cC1j8cJ140GxQXkK1EYNUV80o8Zix7dY7gJMoKBsCA9hXFD9nexFfhUNHwcjYNhR20syWFFJehOjNJIcRPibYc15Zz5AqnBLYgnqo78xogpUJYMsClJ4ZMBWfGSuoWWio9OqVU3LHKfcvBEU6TD3xWTr225Cw6UVNB8c2OqwIA7Q6a+t/mvH1EKysRXxsk8iOTZ6b0PM66iEtEt9tDBAPzCWrAY4c0tCHRFXyq1UuK7lRWVaEnrNlpoFW08Q3zpt1nUR/chEBfQNOITrI8/imqT+CMvM+0hhtK6aokFYHxdOXeFRDOoGeH0/qfVCAnxv/XLz3ZS1+qeivmj6QmjR+3sKYPAMRv9H+YzvZ+ujz2VW59RyMTJaZswXzBmdwYfL8dSxo7tgxp1B0kJiKMfPaTWty3zszKcCc72NXo+hhErdqfA03QPD/w0kYChY+rX321xwuVFltMhDKwG/b4N9mDi5be+8lpEMlQsguMMFUPwJRtiHK+COc2fvo9hujDwtxhvv9KHE3rouXBsqhqVzezXbnSCJRRQg++FNw0pApZIaiBJsa/oIG5PtnyPFCNSfIo9ua1/gp2lt+Y5ipU8AXJTf2RbmbykJqlGUUo45aqA3kHtH++PNVDlbJAwX29qRziiS1OtvUQw4ld30U5+phiaaVP/Zq9GOs0KT0bernuZcmtau2dv27jESU3l4ipL6yaBpqzRfwWluAJhVizirM9O6Ao87LEahalzvTjnml95d+SCjmf0G7HMSGPY3KMiZUoyeOZ94XSMYssRKNnkx3mzxJjPuH7NCW/x0HsUxFLsnDYBl0xtYGKYpIAJoMIzCndZaD3FtRj9AwzhDNe0bsI/BwQ3GizTyr1TGCdXKCy+NaIB+5/E5vfp+1Atqey0P8Ak7ehDSNvs0NwAItMjNWrnKEIBVg7VYs73s8nuf2rXF4uZAbXAoSuljxhpe63JM7roasaBHvCA11M2/rw+vvLgBuLUjdGSbjz245MQBTwuruVCg27RyNT8kyCtDzqJeXC5z1WSLGUUxmd2YN9tJ6/Iasx44EILMV6qJbkfJq2VmcKO/w40/KM8VqOHuZLTQIf8jGWgn6bwgady20kUobrKVMR5/vX2CH8yBxBXtjCmfPede3G74VSjUB3afEelgGPcDQlLia1r0M1Fh9eMQUyQm1zUht6iHGBBfhA0wh3fF2wRVDrMDe0+0nNqknX3VT1GrKm3sZ83xTirO5NNmKXt1SCvF9hpueC718ZnJvfF8o0n29mep33pAy62WtTkR+aMcBEsaDNGqbXfXB6SSg6eDcpc0AaUkawDlnnbPOm3/HVPjpNVngtEy94+cVBDJ9c8ceeBVGj6gcKE2RZYKRLAzxGshUKstkT4aO8i28lAH2rPazurAlVOuVkcJOfXKMMREeoU468NNBQti1Iom7il+PAxKMgRmvgJ24aV+5kSOm6oFyATQE/RAhp1TXP2jWfDhgGlXptbU+Qf11TTOCKYfTmiSVBSwwLZuCxUhEH9NxVCWBHi+OTeuecoa+L6Ma+AZhfFwi9sKOOUsQG0BT9ZApCeg6o4m0XhqXu34iYHlNxowbrnkXKrN7mPzilOALDqGnJSX4hLsSHKT4INypfPH9qanWiFAqnmJ3/E968Jk5ZSa7hRbm4OUL1W0tpfYlsHDeVnANkwLsWBd3PLIe48S/qhzNzmDgFF1Py8fHc5Jp769j2WlTgoponm/1y0YsyBI/ywxaIy1y6fVjKqJC5HqQVjkLs+SrwIFDFUEQ1dzTAbhd5+rEtvz+jgpTGvFpE/7FHohc3iRLx8F6CcVXffFFDZmRcs0VPqmOyJwdVd0x0NECEoTHBvYqrpV3+j+RAkibPFt+7ultMeBxwZY0NQ47GJafHRAg6Y+RiOw2pPUqVRjeiP9lUuAJfH5ACz7iFZ1cIr4zMt9ZSdrdb7kjw/D3JBtVPk95Y4J/iMef6MFf/qMmbf3JhC16y6BnOr0T7rw66NlaD4zpR8jIOHFErzAhJltsxcHmcHA9GoAEAjq76dHMQ6XrJfC5zKlwLLlmndHniu1CKDCQ4PXqqhMn8Fi37/tMV9fhJ3OXliNa3ZV9gBDYZ9M9MYwGE/j5cIK/tpIK1PFdhX6rI9e+MS2rjVuWh5/2vFVrI3WvzFuOVNywdB4JC137UEqxYIaZW7Q1MI/ZrhkLuAN1UUBaEzFopW4Mc3MTK2uSmTa4a8rinCM2ZbWCQQjgGgyhkN0bnrXlVtHeznx/HTGFQQtArTVtVygtTg6+GpvDEQgl2PM4eU0GOe8NuyTPROjOGNh96apt3l+9Egxu6JEY8yl0Wq97Y2GDmk16/Ki0SH/OwA34vSHFxsdFHUkHWHuAqI9V0JL8yZoNW0YASL+w26rbf2Ldm5GHq8XKyIyPoDeLpdgGT32Mf1XqKOFlj/DBbCfQx5ZFC/ifuclNbJa4nGorT/zaiFNoj1AZWBAzik56ysnfp3dGj6XEfJfcftQ+jEeXXwyAPD7XvVI/uXQ7rdKW+ZC3lzKQMvVCQDCn3QRKfQADXkXNFK66y/RLZiPg9aFBKLA/9dDIBa1mLsRgk0pQyqCCfrrL5Tur0eKPM/JFAg5wqYtpHl0wc2zAul8hDfIQI8UEFaDaySgOcSmD9hVJ1d9Ju6Q6Jlu8xwvorK/UeYQDjZ/vkzzzxbvJxILXsLqcnInl7WTswak5kRwvmg8BKKkxo8YQvTp9c1bIwtH3aKLSKTAYDNqSQPv3YZVthoOxfNs3EQRJn9VKa0uZ19E2nHl5FnbrUzl3thPnl662rhNbKBRRWfrOuiLwKx0MzsCdqIoQNhJcFjUZh5KRjWzRVPeIdoiTc4un9yzjbcFu1/bdt7Dd7q4vp9CJlYb8kFHY0KZH2/AF7LLGUYLuL68uh4kKdbw3k83zMwQO3MFRiV4cm7uCNsz0JZmFmYh/+uk0ZFY7CMX+ZkAEpoiT3tLGOVr9ILS8n1dowYK0+PF6t+QWBICSrvkjYRTPEKrQIEsmUVX893EvbQfSMX1h2W7U1XXwcbP6rV1pWhPtmoX6HfKREigcgRvf3EeUOQ0pOMQhVo+lXmhRkcHqsDVF5J6bf0xZ0QTgDEEznQVb/7TUWuhUzTH+yPme9yKYzu7NWPwyoTXA8aNlcxuXLiGHytrfxS5tjcdj2YpmWed2a/uoHeTyBrIMwnwNE/39vsEeOK4CFmdRXoFimwIBhyRJ1QZtdxBimAwCq1xkfF+zZuEOgCsHZRBFP+0gvHBHJg29HoM0/A3p8RrucfFXzylTzr26zUFmUezCi1kIHF/3se+SjhV1D2lhHdVp4hAY9O6AeBFBmwfWByV2vr23g3UJBB22YqKoJG6tA+2QHax2IXY4c7CHdzxVdUZCXUlEGJsxOuhU8NgLEvk//U0+AkflbRxxTFHQnMRnXAJouv81utGIYGIkHdCIz7eSVJMV+YWLsFU76A23y6d7u2L+zvd8Tb3kxYaA35U9kNZbbd4NeGHR6rCnYnx9ufaxo8LDSAqWsH8GRkfxqtND7VNQMK4Fh/iTLXV6aMf/v0XH3EecB99f39Mf6uWhUyNPQlIMHhG30ZzHnXw32HGWgkhkyITbSg9V1FERN7ohQW8A9tFv8OuNRZps1es95IGw1pisq42NF9CCXKBY2t5i/VS06sB5h+tkYSf5VGkq3mb6rO/AZLxqDNNSJ7KCszpyYXzOu+4yhTwy4k9A2a47CwiTzLGgRyQb06tQNY2AEpoVVNuIVygbv3e9CcZjv6ErSAfGJNuBqhHG6Kphor4JZrJmTEq0lWunte3KAXpRHjr1QwP9vym8HiMN2HKuJjFJw5+ziwZtrBhl2hk6IYac3RFXsDvn/oyBipd2mBa3Rez4l1x+vc8w8jEIYT5gDHSOyO7ufnLrGfrM3iKDAujCdFzJUshJgoCY/ryuLLieqmdWqDz2xH1fg/2t2mWzg0BViENG0bf7NdzG7qzH6y6xrHFv4uwvKqloEdyetwT2WgvcY6/U8CQIbbrEW1bYojYszxUQAnb527OsTSZMqDLxCEXoQ4/GeGceaLqw0EAHYplDC9pF3xNjXbAiW1VY6WKNFtl3Ml6/2qAL6GzPLYoMFWgR1v+fhnX6vlJWxrGt7VWiqpvWUKfzyssfud13LNxcwx4sJVz8ejK7jgv77Qo8CHm2pJgf4UWOFL+GybX55euGZeqDc6vYeDV/dzBD9phAvSE9xQqYGNXv/dEFxddPxtdHiDeFULEekiLa2svfD9qjqWOO9SA9UgIxb7ZORqZK5JWaiDjUg5tvC8EbLyX558cyChLgvliXcO/X9MdECYBpMWjyHBGIleEtTyczt3UjcBXJJroTRAVhWDPDppn+RJHuv5Cd7dccCbbOJO7EzoI4A+XyA/sYLoOxyDDVvI7oglQ9wQbyhiDZIy5KLJc75IKKwRqsllIS60gv5a53PuQ3UBnZIYCEGhiCCTLNAzqL7aZlmigdoHFfCnKrg7QDF/OP2YUH2NOMJa2mh1uutZgsqjqXIKqlURm7E998QOG4iwHd+576/UTHoa4UyzwN3jWoG+8Rt1lpuyqiRckEfr/vB3W0hrKHL+T+rcWwVtbc3dU4Rx5hsHoSJxOzTfnAyBAJStVRtm8qivv4LWBjyPe14bZ4+BYfPGiBNdT7m2d5M6c4CtiqNovfmdLTuAEQmZmdcFEPnT8cFSeDp/cuZw4D6c+n9knCFj4T3ukaI5cuIm09GzHti1B5zCr5mGukDRsjxDcAcd4OYjpLFmtaHJf47VQ4YgJbhdDyl6BAKrCqk3nHbUTnMDS/1mChN/NSqmznLzYns7tlrm6Nwp+xSz+X+Hm3FnPd40zDpiCpIGoEq30DT7JITtr25lIy/po7lqbrEBZuhuNL8vz/k2hh8d/bYxjCbJaYBASN7maVeg/wjdrVPJm5oW3ODnsoOw9pT4XQoTVp7YdfFuKGIEnphrIjCMzO8vIvwAAnHZlQ6qU+FMTjuqBgaiD+U/4RJCtrvgcUsQtW1+xeilQk4nwOuJ9dd0mtSW+2YX27tF2RrTX7Wye8GZfUBfUzAOOj/NbZYdce/LWClXdTUFpyHMH673BhCZVfFpdwKifOnDk96rclbzRJfBT7lzIYqdSyZxk21hi3j/iu9uZimdops2rzxlvqYd2PYOfRMfAM2zzqICyGF6nsh9belAWjnHce4hkGcPY0p1xFoIN+RJOUflg6k86nPpLeCuSWDkBdq87uv+ANQHhOOVqpZZNLvfsSlvdU0dP79iVGgbqZ06SQnz7Hdd0elReNH8cMm17OUHhbLlNCWBsOi4EtSgBIaCXVHo+59K1zhsTN6xScR1A/9UDl6ToSOfutFHR3dGSriRUnpYloGzyB74ozqPKVMrA9YdVV1cCTzVvGLJWpfHGPkCy0DxTsBNK0MYxWXDFzTKO3ZwUZlHZj20UEqHe3O6tg2AgME72UFOT9aPZ/errTwDVKip8OLh+9O2ZHh56oN27fLEDBqBTGiLBdfmkxbeskBq5iY38ZoCoGp7Zlirkxk7IDcKxnh2bf4WG37FBgkYtCVN7AR8h8lOsvwLurXX9mvczxW3kO8usWT6SBOH3rwk1qZBD2oJHWJIHnDKVljh9lnmNdMW7DY9m/3rqbSU1X/qmgUDLcScbWQboRIJiSL9ruDLFOdi65Qc6pn54Utr2YOQpqm3Va6SNgQIytMC+DsB9MubUqJe2wMKruIVQ0/A6XkC6S6benIZmuoSyWm2fKolo7iWLcw0aQG9qAY8hTXWzd5DhR0IglH12+KwiQSzFBeKhmQ6OfdtZYBlU7TA2pcdGCdXqoadOOko8T8y5qwGwHZsxdgGhhEqgXx0tm52V1/T93rn97CbPpbIBLDkcmwHL9Sb3r9nd1dXJ8VTNKQMrFfGXrmWk/Q3yToZXDyb07bxCInVMF8PMP/4/o4sKPM5rp5uahwxfdOVDsI9Npyzv+fdtLf87DwSeszdGmVPElV8QFF8F8rGxC1BBUqYoIAON9Rkb0pvmNJU1QunkYJHwB1Qf2F0kIF4RTcZzUv8txKsMmNNsTOyk/YQCAm4OdHUjYOh2Iw/Cp39e8vOtB7rl8+/hyLhDaONbIf2hqHI31CHSewz0B5iZYEp8KXdnX6nH9JjrRfGTWKCC0gtYbquHDbNICzwf6QjHB45+k3x4RCUxORGbZ7dozhUrSWQ4/pyM4WSNLUaxi6Kr6ThwdfARDPrc7CZZJlcCf2dBsFGfMMq4kCtWwbMWQnAikrP9epFgicqaRSvyD6tRALfEsiMamc7qGL8IAA/RwBLrADGtXRjBCNhPo/XjNyi15UD/RxZqnY0WUzRccpkoI1Y9m7q4XDrU+kBhcRDwFd1dr5UimjTQ5YBNfOWZm7fQqvNSp3Ke68cKr9coPSRfFME8iJU7murKo5Y7Wc8Hqdm0qXb02FI64e5BudV1fCoRsBusMlhaFAsGkZr3hP+o+0c4/chRVTX/CYN0eQI2FrYCatrV9jLs5U+M2qw/L27IHdAMDUyeyZBqSM15S5LuPQoUouzvL1Q/wE+pDGFdjaqmnsaACkryWJFEvMrf40Ofu9ts8x9J/vBirnWDJJa6N3OualPCrhL8atPPtuq0rUgGAk0KzX7Lv7DLtbH3sQ89Xk6+rImJZO2s3J/RKFafY5fHN7tTsSOEGMtocrp2JzuqqxsoVmS4CY/nZYZUTsnNeLeBEuntE/xTcYyu3pC0UQDaP1o77Re1PHmjLB6wDGMPBnMC+V0+dEa7xq4LhjnR1t1pF/iKfLsQ2xxGeySQcJNb1veHgeRWiXRimiLuKl23l2oQzTqYfGAtw5u8+nyksWWY4fyQBFZ2DGKY7YVa/7/42B+PsYJkv7Cnqxfig6L/p0Gom2pRlQAllbkCSXbcWJxrw9yTYPW9DF6nlBd94K/xdyOknqY++bRKnENbYKf9uCr+v990BZuew1LqGyp1n3HMe/V1SXa0JP8QQPjx/w6Zt61hZFfu0PTMWiFxFXylu2Xa73Q6iN20DR+RYWCYQzpmUFOddl+fXxzgQA1ADpAjyqpg0vxQjWUU1izYkKZvxFlrhcqTBlbwgHaI2ciVZJxoJ3513RpGkyskPPebqzs2vlPL2d/nGOn03hq+iNxTDb+iLVTxO3fVxV1qV1SLC+aYIe918c7fF5EzaaOIKVqo70Pa3njEMFwI2IQWKydtrV3121YQC+h0n3C9TaJaxr2leQJfLE/WkH7k8qqUnsr1V8eiPNYewHFoZpvy3ok553HCWLSZUrFNPkrjU/3AS+W08BReYDGVQzDg4eZPYwCmNSb4j31wzegAzO9YouZuikHz1VGz+g0qPKBcPjTvYtM0BFj+Ox/rGdtLk0dNXkLfBGAhlSz1kLaEcox4zlKzcSUPpVQ2u8sPp44B+H5aRzH3om5OHoCUcDADbHD/Cs1dFXN/bydIklSH3BoZ41zuAiGrNvGdSGlcJKeoHPsxQIvSFqnaN6pO9VObYkzGVRoZyaPxu5f3RFIvnDIybqJbU+MmhYAywHLXNOfxjzbh7N8IC03TenmCicLAO85xOSBNhYpGT61FVhjFaCbh9TWs/AATaR+g3pbyaxxjzIG2SvvepbXKi44AR/Ym3FqGsvHG7KtrxpctfTgsv01z4d8FEpqT8AL1I/noqEANcb6nEJUYnKlKZdXYbU2Q4JcFN3jg24EnMsBBaOSxZANTClPYWO2YF8QjkSgtkEpiwRkYI3CF/S1PG9+a0nz1iNIRRb6AJ9zjNDBAloXYadDKIBhQJSzo8lz7ngG8xV7CMeeO3lKBKj0njPi+4wdHWTc0/hgHAm+yThEPMdlUeIZWDBeGvhVXF9b2bxbfF+2i3hOz81i5uf5/m3vCilVVXDDFnECOTAi4SN0lV8jXy0n06QCH187BObk4pOkkRffoWR41D1e4XDrPpokH5gHhLFtT4qjHitwWz/EfxrwNSHaYktnLKJXmmC/WfwvSXBpKMUt4lw3QnFT1YR/svW29p+M/MKHNQNVwUSIKnjphRoFRkTe005ye5RC4mopIet+6Jmini7o9fXPqLKI7LskaKPCnD/V5kap/OsSIeDF9cx0FZnuax8MfG2xTksJgrDw50pgoJAEpyNtYTTWbKW7u3xzYn1TltVqDVzaYlZEpv/3RGozuYJAlbk/S8los7dF1cMhfvBubGrXD45UxMvP90udKq03isSWr7PqYH6/I82GBi2PALgLuOU5GhsCmtvhlFTdTxt9f0C9mvGE0K7tVC46vRaTRrej90EDbnJnwzYsRlcmewd6/rIH+m1uklCPLo2sWrysJ/PYbwXBnJwucXCq8oRp6qoC/37GTXaqYAc5Sn6XNa3vnoAAIvY+L/xUqpHC0mPUgSXWDxWr3UzmzHIcmjzuDIX7OKOZbv1L9rEzt8YUip+1FbKCoDJCzxtAToEgrIbE9Zg1VZnFfdIfe1NdMnB9rSrUDUvsL/vcq+P46Wx+VUG+Jm8b3PeH9y3ssy8Dnw/VynsZlmqxKtnefBjC87epQGZ3twjgMeB9vPui1Chbg+nLTBzCaFxOSH/NX0Eh9iI472zPQxwk0u28ZDEFJ8TbVZBBHot7MhYnDXihieqn4lrnVXZPfxD6uN1s2oYbKxRPK+5pPuQzfrouO0HEZcYJZsdl3youilvDPO5n6zwJMA3t4FQ2S03/o1StOtnb4JxfIJu+e4kaflH3bTkXcGe59p4nzqic5TJemCJsp9kWKx3WM2NHpJQnLQjBrhe4nDsFAJt6zRkR+BYWFmfzkfBBBFjrLrZmZxjhAop0WQ3dqZ+WGE6xl/pelKEE3Pk4yti9n/uvHdsp6h6VhBUQ7Xz9X0BFYmUwLY6rOJymYOycHHyxX5iTiHKD+qQHf/gwv4EqIAzr3VKGC0wYCTQsQNuf3K8orcYnmT47vFlOJ95EzfIMvTaXQNhOC9VvB5JNGSbbA4/VsCrD8qoTK0iQeKuFl3J9Yhfr2btBX/f4A0UyfYHNSz3ta+6QAe6O97Ne6ORcuwFHnVYuiyidSHKSAJn0UrLwIEwOk70tYSafIEaX5KT/1aT3KXNFbl5UyzSEAFBMD/CCPzM9imej/VxXQdY9BHTLp0Z8zoTOI0wjPDbVVf9yiE0si5t5UUFOXgcqvvkxYpxD+TT6Pkn4HceY9WrwbbypLzoWm2QR3cl3If+XqFsaANChpAIxtWnchMa3wYICXNl6SIUPgdffF3+EoVfp/HfpfBHcPiHIPPNLmZ/i7B6HGpZUycV3gnorIVivYZsaDTcDX+BIuJk8vt3VUkIuoyi93JWpE1j03JoB10PTzh2F+YhTmvYVjZ1yK7URrTV34Keqgdbi1G9Lo5urqD6YnRByZwsVHMI68Q12/gF4oxChR0QBPcZRHVYQ3YRKD8ZwfbkEtDHWbKBLIWJ0pTuhfIoXamdfdjPRrUIY1+ZH26Bws9IZJlQXzhHLtLNIxB5J5eyvQRSgQOPiV6lDzHZbeDkciay1oJd7pn9vz4zwPnohHus193QNfeVpY6oUjHYzAIJUGqNLVOXbY8JppoREG2uo3vK+pDI55RAa/Uf7747fqpupRxhYw32G94S6CtG5+rVInikmv4ArQ63JXH/DOvsqcqJZU6JLUN/3GGj37YTb6bdbi0Fj+NswEf9uMlueqfasbe2G7oaKuVuHW7k/YgrxWXsTILL3N/sd64g7fuxFimqTj8/akjv7gbDQX2TjBMcTb27FFG5grYO1IVGqnRJbWl+NoF6Aek3UwMcVuFrlUN4DCjEgVPYKSbZNC4oVcVWxS0h7+QKLpNiqT9RsjnsgYsKP9+FgvE9QYM34AgnVQcUOfXa+3yIauN/1QL1v+bc3iNcGKs5QAlNWU22E0WI+t0BapQZ0D/1vxgihHfVE5Xbni1mVV6MvTwkGF0V9IEAJ6Ylwx9ibUEiw0FOK45Lov1jrEqEcCg4+zYKL/OaFxuEwpBfgTXY+jzfy9NV9ArmK82AxABvg1oCe3BEcpEzAl6M+TZVjECFLG2xLFur3XvdV56OJlBSIKs+IyYnTST3otnvKhDYsutjMFx+DT4LUciFPRdLqDmpn8BqSxynAsQ+PM+0rXXoY4GPWcTaeEC0PUBdztcHhC9GGY9hRaYuRrbRvBpWIxieHq0zFJ4GXHgCEAEVSYWJwBYtKDN0Nt10brwB0jQsYTpZ/FDgI2VxOegjA5XWBmYqJaNAXuukGdX31lruJT6x6xzAx13suYiyGwlQwGMJFD2n7virZ4GC08lc5T4Z3eesZ0gonXL+myfXt2FBO+i5GPtsdlJzK4uXAClU8zdEev16HGhiQnbGVyhQ9V5Jq5DCKp0AfaWci2sO/6JAuK/uxqL+7UdadrCogXVgY+ZB4AkPYybjT5srsQWaLrmcK99aq+Cx+Qgp7qOOON+I4ZdYC3s8hHUQqo15R8DoKKIl96ATC0y+UNGHb7QIvzRIEZeYj9RChDj8M7mEHS9MB9pRM49BkAi1njDTDY6cIEWMrGReeiq6P6kmSnfj0zJVSRQGzzL0Yimb8QPYIzCkNZLemCGKEZG8FWfSmgLxFIXwNSn+3Hq8go5Qk+INr6Fsdi9g9OObotKHA5ywQ3nYeEebFSQ9i5hO6fJMuLAyFtIc4EGBHIiE4NHn2TYpQA8I+H7RDwl9FxhpJAgmU8nXyM8pq/d+KWBkPJFA0ltn7BsYx2z/Abv7119YbmBNvCsQ+hoBsSPVIlF18Y4T+d33bt3cIQP0u0MI+2/vw8YWXKCNX58JxeVjM5HyfaaTOfjXOJKfoWzmknkfqPwoKXfHd8BeUZh8nauh4Phe69WYMTJHo57uoxT6ty0JcsUWEpzgUI5mgzO4voUUMdl50X+urGkO1eSqb5+Tj/gBsawEuGxqop8az+e+ZGSpNRSxXxBgjZKJ5o1c6KaCJmfNUmt2e/ilXFCsu636jfXU1uoAnuOnLNHzXWEXu3qbDo5JD+FZ3AreMF0+9ymVdOHOweRp3vwTNTxdItpISglbehh/HkcwZsoALGQKs1B1TJOuNC/6386m5L7tVjNYUN16OglnTkNfd7P/PWJvTND1OXgn19RuyIG67cr0/Z3a44VVVeAmgO2DywCBdFphadzFqManWDg3im1wbCtT9aabrv5tZjaNB8Axgu2yhuPJodEl6ouDf9r1FbIm4AxiIYHc2eKcdcXmaOKObu0uWx9oXfVKGB7wz4N4hwWPC1MoUD7xBtEsTrUjUVstDBcIgQdqJFmuismaXDyHbGrsDsPwq7fvW89rBAwAFFl+X4c43aFY8QdC9Uiwn/w8jTM/AEJOsbase3LTmKH12U1qMuzN0jd7URhhUhoz3wTDKstmiU7ybwvj06TX9C01pBZ7o2mjVEx70QdaRs3DFC/tVnBGuWLcr/UI/r/mR003koQGYlX67oKPcgLOdYmr02RMvhlsdqcNimkrRts9KDPcH5kCq3FaTTBHSwM7DKosPNfLpemIKG6oi7Mm1dNCj/bvIUe48mWVIsmFrVB/kTMW2SS6swO1WKjRSfYgPO1ZXmQeC0u+GkmbuCuCL78gK3Ac4Y59nnZonoKOMt5bp7i9atiiuUolSDA0q4+uA7d33HKRuokxTfUxkg8nDP6cpgqRi2P4RXCDEPxqCZ9M9W3M5ng+nnDMZOmWhySvtBDVMPSC7bcxIWU3qk2S8Cnm8nSL33RfMJ+RuiMRDtGJx6l3170dHfegAOke0cwT1z3i13wt7yo34PTCcRvcXsAXFjNb1fpeljcQbSjmWj9mlMSZLXe8BMTerF98kF9o6uc25/DqyqoMA8MDPkR7w/1mQOLcqX969DIn/hFWHlAQ5g13SSESFsPcvMfyPG8FFaX272I90QQUv8HyO0d206i2vl9tXFi/y1hMhlUZy/sMAWhPE9utNSk0RoqZqfkHFvwsPVW8eKY3CdrhPscjFQ1Rx6sPk+hJS5BQR5LB8hYRoErgTuZUy+0oAr/KDW7uYYN/NsRIiVjC2LJ81Au29N5WKjSMZxv0oSp7v05FLv9mIfeAocPkMRydWRVSdWo29hCLeE0Q/aBgMOFOs+N3Ywsg+TEetMGiLpNuVLNHPuyjUDxvB9f6SlVB7IGKmTtjvDqUXjMn7Uskkiquvr6LIaudK+zk7YPOCwxf1bx6S29ONO8p+WdtUFWMK8tXrcQ7lG6Nk3aECYR0XrMThokSxReBZyXoD9f/SJ31qna9Irp4AglFgT0hSivOTKUP86J4e3RATWUftJfsTlsObd7SHlqoGKf1Whb1wNa7ZJSTLAvw8LVQlsTIDRjfs+LvyJUp/l97iuHFBlBJ/sToeAPaWxfRHvwkkDP0YNAqfa+8rAVtX3LteR/437Be2Dh1sOAwH+y2p3H8lwH8MhikSwQrnuhrXLb+93YJIsI6aYZpkUW0cOmsijblV16mVEInsOomkiYI4ZExN+yK6oKgfHqnKmigS6Y7TQYY5DifbY9E7BJkp4Bm3rctqiYgibl7fOCpxT4INNJUBp+BYO0lGaGZC1H5ybdC8RxdSx14TrMJwV/k58E91IZ8MC/Ds8jSZHp0dgyMZetyvc+l13fw+Kj9sx0eFw/P7ROZR5t+b5KY6S9wFHHCReoHzDABePo8jLwzjeLiS3fdk5Eqtp1SUDSKZ1Ii81q8VjjKTBqHLJeDP9nFFkIhbY8C71wAU7MPb3sShnD9TX6QjLE+OLd85ntm1DGd7LNMN5YB4p8FgcsDOziz0KuuKBOg/nzOz1dw9Bz0ICD8TQDQYRLJgazOPLT95v+RZfPB7gK9KmJAa9wfhnUOCFCChnjSvkWQWKwBiHGuj0kc0X0UWkkeWgjJeL2fmvnBA52w+BER+Vj05FfNJnlG6zjqkoC4WlUzMiF9woWoymCsFBQPVDdZY4nqkWfElH4YLASYxuaDDn8gh5+Zpr/tUXCbhVrevjX/WYIuB2jLOV+A7PZv3iU/lvvXpNIAa9mk+C+C3XVXPXmo/Afi4gC5tVwGOXN8OVjzxpIZF8UiN4kiF/RVmLuxPwP4Vd/YGgAVbX3VMOCrqaAMZ8rnU7+F9BK6wsBSerWy9aa7kWQ9Ht2RFFrXN7mbEgogOtGwdlmbNK0cn+X8Ftv21olaUnDB7ZXBbuhStT756G7yoIdhQ4XMVgKcsFzcG40MXNlzx6htnCZpI/8WYVnSnkEwQt3/+03adsveSJH1DOZanvwCbLKureUXrkRuiSpIhY8uOhdInkcQk0QN6DJ7iqrDItMaNn24FYLQqdFNVXvu6XVYwwW+mGtxtr0I5BfGJTlpyk9EMMD8o6lbohN8Vtbdu8w4C2zkZsC3Jd3cONJ7AXjRj1vtsmYJ90iTMw9qhs7Yz50Qyt5gOQ91oeZsmmCVXF5YQlSlH8ZTxLSWmeZeOO0IzbNprezfOuvOFqSbDhWFtzhP/oQWTqdZ60THeY7tjFIY+qEJsFUEzpDenrVBRL6KMhjdANZLr/J60nF18P0VyFcHCvlUu8C8wfY6JCHYES5sxt8st//5DVdRIuJtwhkNoC0MxIGa9wet/5xKf1VslJvGNEe9FTRGfLGqHFCSnRlCM5/0Kow5FwSvvEfjleHWbaREAyuiXi5u2Zjovx3vGBQXGXxjZ/w0Kr0fc1io59DqEiIX/+hdcYiNKmlPaoCr+xGxVUPqtXI+hugA0nNLzAi2onq5r0D8gxQJ86w/6QXUgIZvFD+mBd2Yv1yict+ItE217W9laUYXQliSaln0CYTfjyAOpM5ICDFDl0kAQmZV0tDuFmqiXgxIPk8jk64VhjWbHd0iOc2FXFPySGFC9olVDuW6yYE4MD+OZdhb7ihPYQfXqZU/Ej85B+Q+ih0TUwWxVoZbl1F3wPKt3TPhCfRy32WQrql5gGU6rUz0TwdW4hySAlu+18/LLdHCJzlc8Zly7nbLCSUO8+tAY8PI8ajZkKHAyWCkvAoxsMZcs1P3HaCI/57iL03pm+KwX9E56FyUgI7c/7CmmR+vkH1n9UHQHJHq9Bjkdb72G2GU+gxA/O+G67rSGtIlAAb7c7g8aZUY/pgHuG07kMCvKPSyv8lCWiaGb1cj4+MnDRBKE9EAD3K293mQOmLyxVwXeBs0hbfh0HxtEqkb+1hC9p47/LpzVoHX4JR0ADMGKdLTCaRvWytHdt74a1Kxno+bKOJRdyVh9GfFsJIulpVxoo0lbnQiB0DHMZRhDfeYZu7xvb8nf4948h5aN/1x2dIuC83ks9soMka24Nd18YdM7+vS/LePgh6GzDIceCCXqqGvmBTChMg1MrT3sgyKlcq7tlvklu/5BuqqI0GS9adn3HHgJjwhdasTtZ7UcafbFFoaVaj9H1vEf67QknXGOC/SicnkO+dfJ7mOFNCrUiI0fZnr5H3gH5t3uHE3OJ0/qmWA6gFlgrGunjRasfUZYwC+y9zDbdjaSv6wkRlJyscKxuLOAGy34ogRKcF+6H0EXLQVoUR+lu6yh05TyuNEXtGDdKOLrr4xphyrTVfWaDZH3oJKBoK5aGHhU7DZsMmYYqYOB214hztfWCrJo0f8pnXMU6invY5o0ouRrrBkov8K+BlyEw8yVOHmFlxB3SRUIuvtf6dpb+A6+LiovLAoEaDHlRoEpIrUdqk0Q9uKTbfkSCsN26oAPHdrZHcXE77QqDRllpa0Sjw1qm6vQtq3e8hitNiepNF86lAChLBJyGcnz2ko0WuT7BzRXoq2uRg67wByg/hxXD9dT4M3SEmhmt19faJgtivZjiXGU3LQCDX3twbF/QuTPfAdTEwlwvUaqr8PJ1z/FGV4KQj6/FPJJBBATqM4i3qCBBGh7bXJ8TojGJOjK8xmJd6GUofqb+8HXrwE+9EV3ZOPbPQJ9swg8vZxoJHCOQ1fOLFi7Vs7ztfA2i+ykMcARDPJiLZDkIdwFyRurJRIRakNo4fHTc6NfgFAlwzFSOF3suNkCWs0awmjJkyNXdEIKq3sT5AsMGNaXRgZIJE3fZoHQ1pVdUyMtV7GJ91MEK4uqg+VRjopYTbPIbbeulq2njZ/TSzzZThUg0B8Q09hxlLBNOi6tctF5UNZSNfmoN0Yi7sbroFlgrdGnHdu4/JjbeMAdaCCY02IKyWRzFyqYMXbjBi9fWCyRt7qDQveoZ/WDL57Dh2z+PkQfxUQ/zWryQS5Gx0l8cZ0sdiUmndtsjDEw6XEkZt4i7pekGltwL6X9H0k3GGT4U+RLi1+6FjJNugZCJwCQXgwOurX7/B1D6JJQFg50Waj2ipwDJcaW+fzLuF+byzfVI2Q5GevA0qrEh1HspID8bPgt9EP+BS/iocPLkJX52wAl951SJd1Ne/oGAFUv5C3HOqtcWQLh/cmApRGtPcw6Wkapwpo8hGwsKDYHBr54tUBroqe6qCg7xenyoYIq0D/S8c8XmIFJ/I3AE5GcRZUsBLSTEIVarvXvyAyJQeBWPRsvE2tTZtMGuxS+20Rqxy232DG7lmgrjLeyY25t+evmDtlS6y2roI+aEoBuGeycqPaoIjDBdd3UnEFNU5U4nkoPbJjMBS9JgEPuLnX7UAKezEb7vUbl1Cj/5TwSXjgGYKpgODs2hA7SvJ1DSuftB29WG6pEqjt4mKHw/cOs1X8PnpEQ6XUIeHSZkM0w8UCWrHJxVFtck/Xcsg3dtk1crzAoVzwO1Grjg731jVNNJrQxk3rV4WdBBfpHCwG7Kk0d4sAyLrxDSOiio6aAnghCvsWRNV0Mz40Fzb/3OzExlNHEwA9YnCZi4nuwbDJiO714okB8QbiRMJRkPCfdU/r0NzytET8xtpI7s5E3Ol8yUrWJj1DNM7gGsxeUG7dD7wGOpA7IYwqWG31525E0y8ZIytZknSLcN35uDHJ8Eym6lqdxRdg/uHLpxUk7SL6Dn+TIe+eii3ubEj90lVL4c2joA5puYslDoTaWrsfEHJ7iyrKGa7g5DHWxkcB995Zk5coL9hSowZASKdWMpQ0HR2Dv/ZnDkO523WXlF0F35vTkIxtjjn48CUXMfzGjmEhKOWACYonLbikFqpvQ/VM0XTPSbmQg7LNw2FUN9itOTb4aOaCb74LC88F++KJ4azDVYVpxXC35bfsqdgK2lngxfFqhMOGEYe73c8l9Ti5gli2PejI6Hm0y90SygCRfiI6fOa2qBoMKOnoLyW4M051d/uz/Q3vRIgo1P0Q+LmgPlLrKjxxWE4Bz8pS3H0OwC4Z93RPMcTCrhAWmxmwSWNNndKUdI+0Cbkfl5NFeccJxVvBNCDiocwbXMMekEFPuotzsvo9lngvUru3K8eFcopeLEGL3jR+UWaJHrk2TrBBkQ0LYWzBJhp+607Jupq/ElEu26yMPKXR6iXUkbPYK8X4grUI47PUy+1LtCHadoazQVT3YrnDkjVausHVJuhSkB8HGf8uvEfustVvOxc7yxkqMj/ThLtVCXKUFbo514Q88t2deE0aslFeC2QXc8dd5MfIrdvDwRXeYAidIUcj4VX5gt2Qcf/54oL6jplPcFRBMhLBc5d0GzkyG+TLqswZywo6duCrgEMf0KJL0FqUoAAsAxpznuCSr2YTMBXza60MnzBFouGOqECR4D2/6+fbtJOUWEuuf3i8zUQqdJVuQHbbOmTX/TWVw14Nbp5gzk3pi6SdGS56VW+/tf30XRCWgIUvvxcIdWWU41PDSyKrTiGhnuMK3H/b4dEm7DaK2lAm82X+Kgodm1uebg4E0ZvcN/xFx28XHAv3hFd0JqpIyLXcLa+ZJMF3cOJqINMgJ/uf1ZZBCHNWbY7AHPm+caqMzXDesYXx1J6lzFEaVuOpTSO2alVO+QxSTNsspNCdV9P4VrdtmCt8uthsLAkDlJuOdxKHzMNcg0X/f+pHKZSCrWEfku9D65SwSVBkTi2pwsK938lkTrSxPJylUfTwMP2x0FSfI2/nVVBJiZlB5mW2JCdW0/gGxtTCfxdIIzg2FvW+mLs0WTZfazUrMbQFFuquta+Gb6Gb+2SPTAaoNXGJPh7K7ZL6VpUTrIhzizjFM0uQXa9r98cf5iVRYwd+rZOA6igLquS9HDW9PTCovyUpCMiaSBVGpaT42g+oRg189L/KBHkjs78sOXhPEq6GW4O9BRotmFpBJgW5MhszrALMyQ0UoXRu6PtzwxBM6fZfcUZiC1EToOB1DBnViKwFtCLUXiZWQqZubJvIniUFR0iltSENPRFEystHmLOyusYIsyFK37PGaY2bC6GuSkAKZ4uC6i+qmPeroh3Q1nygH8FXRZsrURAnxmupwMNuz0woWtbK+y5X5L3hypaAU3Hbhj0hJlJkkpZtplYAhNKuHByrdOn2A/+0Ls1kn++XZJoZfM//Ig0i3PR/d/08dGitolRuULJHrdZvVsGHSIj8XjQZqGKcMlI6C20OrU6wytTx5GuINb/6XglyLCLUAl9vPzIz6xay+tdR9FywQhTDedF/Y7JboQl7/RRSYk35ungaCIDTdh8OwqMJj/uFKrWYFRSJ9GZyU/trS3+R+1mV8M28KGNBv/xe/751MjEaC5bex/tcoO1IiM22vhOdFQe591EVGYw6NwJw2Sfk9nFnZFNGLEVncVbgH+7KE142Ekx/GcXUHq0AxwdfLx/cbRek2T/Vk4Q3vkYOSXmk6FqbuKddTv/z/Z5EF4LMV0OrJvIkepmPTpHX8PP1gEMn2nwsd6azE0ql2KO6nh1SN5UIFvdtJFuh6f2I2NsBkbG6lpQ+y+zUIGjn4KYqeSS5bMvk0rrADmR5HjxI9H6VH8GKWkThx38o3AzcMP08yelp4GZS1tJbiuXfLoOFjBoyFnf+0vOmXmzrbn+xBtIoWmBT1eP1E1tsJGOKLlLv42nMdd6glcxhx/NkK9tInZgYkrlz5q4ENQqbwgYAZe6a1fcKkPWXpqJLDMSlfFtc3f5E0kfYxbDYKY+rH0PZH2RPzrpOu6N7SaXrNoDPFw+iST6e6OeG10Hw4I6QzPPTY4yqFTP5/ec/wXu29bVhVcNgnYPddBo8dh0682XdpSMlLzJQez88fb56smkUlxIVpCBAojB/UlyTVtxEk6IDD91mVPrILdLHX5epz4QXUWx2VUOH2zpV2zZHIZZH+0RVupo13g9hirIzGobxfYTAm+no0p572sxAjUCgPiMC3Zz6Ks+qrWLilGMIhMYrdKk+r3H5PxyN81BPx7vErZwuSfCk3PptawcEvnDaP04XgbZ1udyCG45MUOzqdW0wBxj1MVyP06NU5n6ZBU626RFnO0qsCA3oCiTbTs+QAH3QOQ9sQDGqk8ylCzVpDSrhvctRwJBw2as924DZP8fhCTI1svc/c8+LJqsIfAR6ZdzIBGa/zhBTrDSZm+zlI4zHK0UZDLVW/DM0SXy05cfhtgdWIN2mXrSsDy45pDPwuOi4x5NJVAfLRkKAZCF08BS8uj4PfzX+slOb/sCmMgRt5VKIUdKxkkbTW6fzSwruemdIX+N/CPpkKr8TAg9/BpD4Up5thQWmO35GI3QFwZsz8yzHsqLc+ooQ1p6Uf31Cd03t6K1zk7yEet2EzcnZOOBliw5wZC7pBAVCZ31nKDWBRb3G58C35NZ87AAgQTLFF5XJ+VX4ADPVfrtIbB/YQf5ok76Te6Nybei+MPH3zo/3oG74+Y3J3ShYmigN4TvU9Jqurn9n9MslVyd/nil3pfRv3JElLKYTPe3n8sQl/W+pvwFayXEZSbiyEq0CKC7yQKER4dFkU9AciEMAAI1q6mbgQSc3uZEwaKTQvenTv7Cn1V0BFESuhCAImxmtCiSLtFHDwaoBXweoFp8h3lzMVYUatT34LuZ2Sfzjm62iC5loxdxydV2AdYLeX9tmmln0ineBqUXB5rXYchRxPWvZzGGQDhlX36k+qd9J32F1FAdWxrUUducpzEv8ePpEKXsLhGF++6g0Q2m2yADVX4IVxgol2XfiQiqqTqh8fmALto5VRrTfC9rXIAAJcOYV/xhLD6sBNevLASLGq1Ssq8FBHRdaR8PZ8jZkvleO8gXov9XEaG7Z0CXaiIuG/Y5PhvXFT0pDs+r4PaLi+c+xIhZX3e4sjDnmBzmy8t7eeGGPX6dQhzvTfV4qcQzXqytz10uc+WMX08Mnr2fIwaND97KbqXvX9DlH5DWptdFOMeXq5Fw4dhVd+VAWYi7N0g/4/0PI0KmYoupNbsL3jTUB7+hF3fkY5/8o09HBxJ+Y45hfElxpluO86Uwi4fQivFeKvSGIzLlALjjcuCkljFC+VbY/NRv00Z0Mv+GakDsOHedBez5WlNC2f3CpzHfU5avFpNBQsyPBnJPaUfLrMje9P3qhyNsoMNBptOPSauBK2zw5mvw97BV1+4UlgAaORB3lLW6O2VYkVTh1U3WvTmJcUwkOn5jJaKSrlDKd48XR+il5vmmYrn5pdrjMTNTYMrQKCBAGrOzlqTuuGDE71DFHOlBZegUiRDOejyv1rKwePFzqSXjsbmYz86HKu3IF1F45stD3yqRudxHwXUl5rIr67I6TRnrx0u+BlD2+wb3A/sIqgqGEVm2EM/MtGCQ+KlWxzhi/jTKnVXE+V3Yb3+ub3qEGnXmj0B/zvVmEYiw16mGYgq9gXw9bJirxOzmP2X5Dd1uDWd1oJcKjmzr4aEgTT6qQ5bd25Ry/TxxB3bU1moqHdM84naQ4M48q7z94kOh/5Zemxz3a5a3Sv8d3rBLnJY/QuWFzXnBBEOxYNlryJ03VKhvRYFqHKTiEZYUz74AHBisnwoJa3qZ917dis5C3ld9TUaEZjsVeIMZhOFBe++47d8P98O8fLhWZeMz2Ti9E2x/c7OfPPv3kTI7Aw6mPHAwmMGf1PgtQziz9Whw/9IPSHsdnvqO4SUI747u3jZpola/fhKMlDiIjNc2o0nYQNSNOvQZTqq9kjei3gLM/AwFD/jLaE96RZJxg0RhyAeNS5bd39DyYJyNAGwZe6HqnAZQMtXoditaYp03OOf/zwskxI2hWvkqGwQzKIhlkb2uZBJMYBfvo4juVEL1BoZWKXfngUCkCCLeXH7hIdnjC+yHBU2pGfkZS2Zka5VJNXwx+0wG4uZFOd1t1ftYfvHh1nR3ej7ZHjtAZb5ZWrqEuyYW5y/0GfALD8tJ5zTDzQNQiXQmFv4lNr3KAXJGkLmlvD3c1YjZ2ySaLmzGijr3lqpfK4nZxeV+K4KapskbI0qI5E+SusD4trwO0Q1gopVMQt0IuWs0F4mZf7xg5Ly24Nb4P1Kqy8mG8fwaYsB6CPvr8WYRWqjypmTTyKuou5wlSOUq2QRyVQoBiEGwzUSPHduCDhxVGsZZJUokE0fSfRKsHDMpDVfMcnbzyUVkeBRp9q770sP1UgWhP0Ym6abxDHA1q/MuUINeJbyINpZWkaK80kPVuDMSifMgWnp9Hu+7HsJEseNtNrPGWzSmclAL7bQhkdcjNKRustrL1/xSDNW1/QGG3J7OIX95UmwCNLweHK1PnJvry1bvrgHRqLRj4bs4wepeLZ5SsaoKpaX1O0M/47g9xvHMKvUSa81F2DbQKSMgQieFozYAKlmbKlQe95h19xTWVJl3mpT50rfTef1KyORxWxWgwtueCsEXGnfkyoHiLQA+toUmjuxbV1zjRDOc5Pgy4W9HfBKV3A3i65nVt2RIA00dtiVon1+JpYxTGxMb/PtzR1Q8yB9huLYDMToKCM8XC+lWd9JSG9AuA8vupJsgYat15K0/1/eeToSlLQZuE4qD7Poq5Pq810U9A8K3/8fuWpPVpSHo6+r6xahrjs9+exhl7Px87CHrs95cLS9RzCqLnRQ7KDqow+FrrHXkjpKDPrgoycNh2cCA2/HcV5MGBWnA4J6tNrjb74V3gJcvqd/QhdxM3xmS4AQ","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"53ce981e551c2c7b4b2f9bc49ee0c60654c40364","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-86","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"227-257","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"452-498","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"a979596d6efe10d64710b17a20f51f7568585f40","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file diff --git a/02-SERVICES.md b/02-SERVICES.md index b541f22..f6fb180 100644 --- a/02-SERVICES.md +++ b/02-SERVICES.md @@ -56,8 +56,8 @@ class ResourceCalculationService 'total_allocated' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], ]; - foreach ($nodes as $node) { - $nodeAvailability = $this->calculateNodeAvailability($node); + foreach ($nodes as $nodeWithServers) { + $nodeAvailability = $this->calculateNodeAvailability($nodeWithServers); $locationData['nodes'][] = $nodeAvailability; // Track maximum available across all nodes @@ -90,9 +90,10 @@ class ResourceCalculationService /** * Calculate available resources for a specific node */ - public function calculateNodeAvailability(array $node): array + public function calculateNodeAvailability(array $nodeWithServers): array { - $servers = $this->fetchServersOnNode($node['id']); + $node = $nodeWithServers['node']; + $servers = $nodeWithServers['servers']; // Sum allocated resources from all servers $allocated = ['memory' => 0, 'cpu' => 0, 'disk' => 0]; @@ -227,36 +228,25 @@ class ResourceCalculationService 'Authorization' => 'Bearer ' . $this->apiKey, 'Accept' => 'application/json', 'Content-Type' => 'application/json', - ])->get("{$this->apiUrl}/api/application/nodes", [ - 'filter[location_id]' => $locationId, - 'per_page' => 100, + ])->get("{$this->apiUrl}/api/application/locations/{$locationId}", [ + 'include' => 'nodes,servers', ]); if (!$response->successful()) { - throw new \RuntimeException('Failed to fetch nodes: ' . $response->body()); + throw new \RuntimeException('Failed to fetch location: ' . $response->body()); } - - return collect($response->json('data', [])) - ->map(fn($node) => $node['attributes']) - ->toArray(); - } - - private function fetchServersOnNode(int $nodeId): array - { - $response = Http::withHeaders([ - 'Authorization' => 'Bearer ' . $this->apiKey, - 'Accept' => 'application/json', - ])->get("{$this->apiUrl}/api/application/nodes/{$nodeId}", [ - 'include' => 'servers', - ]); - - if (!$response->successful()) { - throw new \RuntimeException('Failed to fetch node details'); - } - - return collect($response->json('attributes.relationships.servers.data', [])) + + $attributes = $response->json('attributes', []); + $serversByNode = collect(data_get($attributes, 'relationships.servers.data', [])) ->map(fn($server) => $server['attributes']) - ->toArray(); + ->groupBy('node'); + + return collect(data_get($attributes, 'relationships.nodes.data', [])) + ->map(fn($node) => [ + 'node' => $node['attributes'], + 'servers' => $serversByNode->get($node['attributes']['id'], collect())->values()->all(), + ]) + ->all(); } private function getPendingReservations(int $nodeId): array diff --git a/08-ALGORITHMS.md b/08-ALGORITHMS.md index 2987eca..bc3722c 100644 --- a/08-ALGORITHMS.md +++ b/08-ALGORITHMS.md @@ -145,7 +145,7 @@ CPU is NOT overallocated (uses thread count × 100). ┌─────────────────────────────────────────────────────────────────┐ │ Pterodactyl API │ ├─────────────────────────────────────────────────────────────────┤ -│ GET /api/application/nodes/{id}?include=servers │ +│ GET /api/application/locations/{id}?include=nodes,servers │ │ │ │ Returns: │ │ - node.memory (base capacity) │ diff --git a/09-IMPLEMENTATION.md b/09-IMPLEMENTATION.md index 0539909..367a6bf 100644 --- a/09-IMPLEMENTATION.md +++ b/09-IMPLEMENTATION.md @@ -85,7 +85,7 @@ Improvement items from the 2026-04-26 audit pass: - **dp-14**: Rate-limit reservation endpoints to 10 req/min per authenticated user — ✅ Shipped (PR #17) - **dp-16**: Documentation sync: align 03-API + 05-ADMIN-UI + 09-IMPLEMENTATION with post-dp-13 architecture — ✅ Shipped (this PR) - **dp-17**: Alert delivery log + `AlertDeliveryFailed` escalation event — ✅ Shipped (PR #18) -- **dp-18**: Capacity-fanout performance: batch Pterodactyl reads in `ResourceCalculationService` to reduce O(locations × nodes) API calls in admin views — Pending +- **dp-18**: Capacity-fanout performance: batch Pterodactyl reads in `ResourceCalculationService` to reduce O(locations × nodes) API calls in admin views — ✅ Shipped (PR #20) --- diff --git a/PROGRESS.md b/PROGRESS.md index 29578ec..32dc190 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -6,9 +6,9 @@ Active implementation tracking. **Claude: Update this as you work.** ## Current Status -**Phase**: dp-20 reservation lifecycle close-out (shipped as part of dp-19) -**Last Updated**: 2026-04-28 -**Last Session**: dp-20 audit pass confirmed all 4 changes (cart-clear race fix, confirm-return logging, cleanup cron, expires_at guard) were already implemented in dp-19 commit `a861479`. All 128 tests green. Plan closed out. +**Phase**: Panel/GitHub reconciliation and Qoder Wiki refresh +**Last Updated**: 2026-08-17 +**Last Session**: Preserved the dp-20 close-out, reconciled the location availability batching work, hardened the standalone Windows test database guard, and refreshed the Qoder/GitHub Wiki documentation for the batched `locations/{id}?include=nodes,servers` flow. --- @@ -16,7 +16,7 @@ Active implementation tracking. **Claude: Update this as you work.** > **For Claude**: Read this + "Current Session State" to quickly understand where we are. -All documentation and scaffolding complete. 9 spec files + 4 support files (CLAUDE.md, DECISIONS.md, PROGRESS.md, CHANGELOG.md) + skeleton directory. Ready to begin Phase 1: Database migrations and core models. Start with 01-DATABASE.md. +All dp-NN backlog items are implemented. The active reconciliation is staged on `agent/reconcile-dynamic-and-wiki` and published as draft PR #23. Mutagen deployment remains paused until review and merge. --- @@ -67,11 +67,11 @@ All documentation and scaffolding complete. 9 spec files + 4 support files (CLAU > **Claude**: Update this frequently during work, not just at session end. > This survives compaction and helps resume quickly. -**Last checkpoint**: 2026-04-27 -**Working on**: No active task -**Status**: dp-19 shipped. `dynamicSliderGroup` Alpine wired to reservation API; guest support via `checkout` middleware; `Cart::checkout()` confirms reservations with extension-disabled fallback. CodeRabbit findings fixed (Alpine x-data fallback + obsidian theme sync). +**Last checkpoint**: 2026-08-17 +**Working on**: Draft PR #23 reconciliation and Wiki verification +**Status**: Panel changes are preserved on the reconciliation branch; Qoder Wiki pages are migrated to GitHub Wiki and refreshed for the final batched location API flow. **Current file**: PROGRESS.md -**Next action**: All dp-NN backlog items complete. Next work determined by driver. +**Next action**: Complete exact-SHA review, then merge draft PR #23 when approved. Resume Mutagen only as a separately authorized deployment step. **Blockers**: None ### This Session's Changes: From 6347021b818330bed952caf95cd89664be51c05f Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 19:44:12 +1000 Subject: [PATCH 07/95] docs: remove residual per-node wiki flow --- .../Public API Endpoints/Availability Endpoints.md | 2 +- .../Architecture Overview/Companion Extension Pattern.md | 4 ++-- .../Event-Driven Architecture/Event-Driven Architecture.md | 4 ++-- .../Service Layer Design/Resource Calculation Service.md | 6 +++--- .../Service Layer Design/Service Layer Design.md | 4 ++-- .../en/content/Core Services/ResourceCalculationService.md | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md index 1bcf6d1..cb1a8b0 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md @@ -207,7 +207,7 @@ Why node-level details are not exposed ```mermaid flowchart TD -Start(["getLocationAvailability(locationId)"]) --> FetchNodes["Fetch nodes in location"] +Start(["getLocationAvailability(locationId)"]) --> FetchNodes["Fetch location with nodes and servers"] FetchNodes --> ForEachNode{"For each node"} ForEachNode --> |Yes| CalcNode["Calculate node availability
from servers + reservations"] CalcNode --> UpdateMax["Update max_available per resource"] diff --git a/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md b/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md index 5bdcab6..8936ad7 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md @@ -201,7 +201,7 @@ participant RSC as "ResourceCalculationService" participant Ptero as "Pterodactyl API" participant DB as "Reservations DB" Controller->>RSC : getLocationAvailability(locationId) -RSC->>Ptero : GET nodes (filtered by location) +RSC->>Ptero : GET /locations/{id}?include=nodes,servers Ptero-->>RSC : nodes loop For each node RSC->>Ptero : GET node with servers @@ -363,4 +363,4 @@ Common issues and diagnostics: ## Conclusion Dynamic Pterodactyl implements a robust companion extension pattern that enhances Paymenter’s built-in Pterodactyl integration without replacing core functionality. It maintains separation of concerns by delegating pricing to core while owning reservations, availability, and alerts. The extension lifecycle is cleanly managed through installation, boot, and scheduled tasks, and it integrates deeply with Paymenter’s event system to ensure reliable checkout flows. Real-time API access, pessimistic locking, and thorough auditing provide correctness and observability, while admin tools and Filament 4 interfaces offer operational control. -[No sources needed since this section summarizes without analyzing specific files] \ No newline at end of file +[No sources needed since this section summarizes without analyzing specific files] diff --git a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event-Driven Architecture.md b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event-Driven Architecture.md index fb541f6..378c14b 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event-Driven Architecture.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event-Driven Architecture.md @@ -333,7 +333,7 @@ Responsibilities: ```mermaid flowchart TD -A["verifyAvailability(nodeId, requirements, excludeToken)"] --> B["Fetch nodes in location"] +A["verifyAvailability(nodeId, requirements, excludeToken)"] --> B["Fetch location with nodes and servers"] B --> C["Find target node"] C --> D["Calculate node availability"] D --> E["Sum allocated resources across servers"] @@ -434,4 +434,4 @@ Operational checks: ## Conclusion The extension implements a robust, event-driven checkout flow that reserves resources during cart operations, confirms them upon payment with real-time availability checks, and maintains comprehensive audit trails. Concurrency is handled through pessimistic locking and retries, while scheduled tasks ensure data consistency. This design balances reliability, performance, and observability across the payment and provisioning workflow. -[No sources needed since this section summarizes without analyzing specific files] \ No newline at end of file +[No sources needed since this section summarizes without analyzing specific files] diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md index b77aa71..bebc0fd 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md @@ -87,7 +87,7 @@ participant D as "Local DB" C->>A : GET /availability/{locationId} A->>N : getMaxAvailable(locationId) N->>S : getLocationAvailability(locationId) -S->>P : GET nodes (filtered by location) +S->>P : GET /locations/{id}?include=nodes,servers S->>P : GET node + servers (include=servers) S->>D : SUM pending reservations (node_id, pending, not expired) S-->>N : Node availability arrays @@ -125,7 +125,7 @@ Examples of usage patterns: ```mermaid flowchart TD -Start(["getLocationAvailability"]) --> FetchNodes["Fetch nodes in location"] +Start(["getLocationAvailability"]) --> FetchNodes["Fetch location with nodes and servers"] FetchNodes --> LoopNodes{"For each node"} LoopNodes --> |Yes| CalcNode["Calculate node availability"] CalcNode --> UpdateMax["Update max_available per resource"] @@ -253,4 +253,4 @@ ResourceCalculationService delivers accurate, real-time resource availability by The service balances accuracy with performance through pagination, batching, and targeted retries, while ensuring robust error handling and safe degradation when Pterodactyl is unavailable. Customer-facing endpoints remain privacy-preserving by exposing only aggregated maxima, reserving node-level detail for administrative use. -[No sources needed since this section summarizes without analyzing specific files] \ No newline at end of file +[No sources needed since this section summarizes without analyzing specific files] diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md index 3ed0163..ef0ac3c 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md @@ -131,7 +131,7 @@ Error handling: ```mermaid flowchart TD -Start(["getLocationAvailability"]) --> FetchNodes["Fetch nodes in location"] +Start(["getLocationAvailability"]) --> FetchNodes["Fetch location with nodes and servers"] FetchNodes --> ForEachNode["For each node"] ForEachNode --> CalcNode["Calculate node availability
+ pending reservations"] CalcNode --> Aggregate["Aggregate totals and max available"] @@ -350,4 +350,4 @@ The service layer cleanly separates concerns: This design supports robust workflows across checkout, confirmation, cancellation, and monitoring, while maintaining clear boundaries and graceful degradation when external systems are unavailable. -[No sources needed since this section summarizes without analyzing specific files] \ No newline at end of file +[No sources needed since this section summarizes without analyzing specific files] diff --git a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md index 95685e9..1774501 100644 --- a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md +++ b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md @@ -132,8 +132,8 @@ Return value: - total_allocated: sum of allocated resources across nodes Processing logic: -- Fetches nodes in the location via Pterodactyl -- For each node, fetches servers and pending reservations +- Fetches the location with included nodes and servers in one Pterodactyl request +- Groups included servers by node and fetches pending reservations for each node - Computes effective totals using overallocation settings - Subtracts allocated and reserved resources to derive available - Aggregates max and totals across nodes From 1d8ce1a0053e111bbbe85e12da5e016ab1796a3f Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 20:07:57 +1000 Subject: [PATCH 08/95] fix: harden test isolation and availability errors --- DECISIONS.md | 2 +- DynamicPterodactyl.php | 2 +- .../Api/AvailabilityController.php | 9 ++-- Services/ResourceCalculationService.php | 44 ++++++++++++----- tests/AGENTS.md | 2 +- tests/Feature/AvailabilityApiTest.php | 22 +++++++++ tests/TestDatabaseGuard.php | 47 ++++++++++++++++--- tests/Unit/ResourceCalculationServiceTest.php | 22 +++++++++ tests/Unit/TestDatabaseGuardTest.php | 26 ++++++++++ 9 files changed, 153 insertions(+), 23 deletions(-) diff --git a/DECISIONS.md b/DECISIONS.md index ac54ab6..097e606 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -244,7 +244,7 @@ Unit coverage accepted for dp-06. The full Filament-action lifecycle end-to-end ### 6. Test Isolation Mandate (dp-13, Apr 2026) -Extension phpunit MUST set `CACHE_STORE=array`, `SESSION_DRIVER=array`, `QUEUE_CONNECTION=sync`, `MAIL_MAILER=array`, `BCRYPT_ROUNDS=4`, `PULSE_ENABLED=false`, `TELESCOPE_ENABLED=false` — mirroring the root `phpunit.xml`. Failure to do so risks polluting the shared Redis/file cache on a development host, corrupting the settings key read by running web workers. This caused a production outage on 2026-04-23. The `bootstrap.php` guard provides a second line of defence: it accepts only `paymenter_test`, `:memory:`, or a strictly named `dynamic-pterodactyl-test-*.sqlite` file directly inside the system temp directory. Empty database names and arbitrary SQLite paths remain forbidden. See `incidents.md` for forensics. +Extension phpunit MUST set `CACHE_STORE=array`, `SESSION_DRIVER=array`, `QUEUE_CONNECTION=sync`, `MAIL_MAILER=array`, `BCRYPT_ROUNDS=4`, `PULSE_ENABLED=false`, `TELESCOPE_ENABLED=false` — mirroring the root `phpunit.xml`. Failure to do so risks polluting the shared Redis/file cache on a development host, corrupting the settings key read by running web workers. This caused a production outage on 2026-04-23. The `bootstrap.php` guard provides a second line of defence: it requires `APP_ENV=testing` and accepts only `paymenter_test`, `:memory:`, or a strictly named `dynamic-pterodactyl-test-*.sqlite` file directly inside the system temp directory. Existing SQLite files must resolve inside that directory and have exactly one filesystem link, preventing symlink and hard-link aliases. Empty database names and arbitrary SQLite paths remain forbidden. See `incidents.md` for forensics. ### 7. SetupWizard Atomicity Contract (dp-13, Apr 2026) diff --git a/DynamicPterodactyl.php b/DynamicPterodactyl.php index 229021d..d94042a 100644 --- a/DynamicPterodactyl.php +++ b/DynamicPterodactyl.php @@ -60,7 +60,7 @@ public function getConfig($values = []): array 'name' => 'pterodactyl_api_key', 'label' => 'Pterodactyl API Key', 'type' => 'password', - 'description' => 'Application API key from Pterodactyl admin panel', + 'description' => 'Application API key with read access to Locations, Nodes, and Servers', 'required' => true, ], [ diff --git a/Http/Controllers/Api/AvailabilityController.php b/Http/Controllers/Api/AvailabilityController.php index 8b66e38..5965526 100644 --- a/Http/Controllers/Api/AvailabilityController.php +++ b/Http/Controllers/Api/AvailabilityController.php @@ -42,11 +42,12 @@ public function getByLocation(int $locationId): JsonResponse 'resource_capacity' => $resourceCapacity, ], ]); - } catch (\Exception $e) { + } catch (\Throwable $e) { + \report($e); + return response()->json([ 'success' => false, 'message' => 'Failed to fetch availability', - 'error' => $e->getMessage(), ], 500); } } @@ -60,7 +61,9 @@ public function getNodes(int $locationId): JsonResponse 'success' => true, 'data' => $locationData, ]); - } catch (\Exception $e) { + } catch (\Throwable $e) { + \report($e); + return response()->json([ 'success' => false, 'message' => 'Failed to fetch node details', diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index 3b66c8c..f99bacd 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -231,22 +231,30 @@ private function fetchNodesInLocation(int $locationId): array ['include' => 'nodes,servers'] ); - $nodesData = $response['attributes']['relationships']['nodes']['data'] ?? []; - $serversData = $response['attributes']['relationships']['servers']['data'] ?? []; + $nodesData = $this->extractRelationshipData($response, 'nodes'); + $serversData = $this->extractRelationshipData($response, 'servers'); // Group servers by node_id for per-node allocation accounting $serversByNode = []; foreach ($serversData as $server) { - $nodeId = $server['attributes']['node'] ?? null; + $attributes = is_array($server) && is_array($server['attributes'] ?? null) + ? $server['attributes'] + : null; + $nodeId = $attributes['node'] ?? null; if ($nodeId === null) { continue; } - $serversByNode[$nodeId][] = $server['attributes']; + $serversByNode[$nodeId][] = $attributes; } $nodes = []; foreach ($nodesData as $node) { - $attrs = $node['attributes']; + $attrs = is_array($node) && is_array($node['attributes'] ?? null) + ? $node['attributes'] + : null; + if ($attrs === null || ! isset($attrs['id'], $attrs['name'], $attrs['fqdn'], $attrs['memory'], $attrs['disk'])) { + continue; + } $nodeId = $attrs['id']; $nodes[] = [ 'node' => $attrs, @@ -261,9 +269,10 @@ private function buildNodeAvailabilityFromServers(array $node, array $servers, a { $allocated = ['memory' => 0, 'cpu' => 0, 'disk' => 0]; foreach ($servers as $server) { - $allocated['memory'] += $server['limits']['memory'] ?? 0; - $allocated['cpu'] += $server['limits']['cpu'] ?? 0; - $allocated['disk'] += $server['limits']['disk'] ?? 0; + $limits = is_array($server['limits'] ?? null) ? $server['limits'] : []; + $allocated['memory'] += $limits['memory'] ?? 0; + $allocated['cpu'] += $limits['cpu'] ?? 0; + $allocated['disk'] += $limits['disk'] ?? 0; } $effectiveMemory = $node['memory'] * (1 + ($node['memory_overallocate'] ?? 0) / 100); @@ -398,9 +407,22 @@ private function pterodactylGetPaginatedData(string $path, array $query = []): a private function extractRelationshipData(array $payload, string $relationship): array { - return $payload['attributes']['relationships'][$relationship]['data'] - ?? $payload['relationships'][$relationship]['data'] - ?? []; + $attributes = is_array($payload['attributes'] ?? null) ? $payload['attributes'] : []; + $relationshipSets = [ + is_array($attributes['relationships'] ?? null) ? $attributes['relationships'] : [], + is_array($payload['relationships'] ?? null) ? $payload['relationships'] : [], + ]; + + foreach ($relationshipSets as $relationships) { + $entry = is_array($relationships[$relationship] ?? null) + ? $relationships[$relationship] + : []; + if (is_array($entry['data'] ?? null)) { + return $entry['data']; + } + } + + return []; } private function emptyClusterSnapshot(): array diff --git a/tests/AGENTS.md b/tests/AGENTS.md index ba3c87d..83760d1 100644 --- a/tests/AGENTS.md +++ b/tests/AGENTS.md @@ -40,7 +40,7 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p - Any DB-writing test must use `Illuminate\Foundation\Testing\DatabaseTransactions`; this includes DB-backed `Unit/` tests and all current API feature tests. - Feature API tests must `require __DIR__ . '/../../routes/api.php';` in `setUp()` because extension routes are loaded manually by `DynamicPterodactyl::boot()` at runtime. - For schedule assertions, boot the extension in the test and inspect `app(Schedule::class)->events()`; no local Job/Command classes exist. -- The bootstrap refuses unsafe databases: `DB_DATABASE` must be `paymenter_test`, `:memory:`, or a `dynamic-pterodactyl-test-*.sqlite` file directly inside the system temp directory before Laravel boots. An empty value is rejected so the application cannot fall through to a production `.env` database after the guard runs. +- The bootstrap refuses unsafe databases and requires `APP_ENV=testing`. `DB_DATABASE` must be `paymenter_test`, `:memory:`, or a `dynamic-pterodactyl-test-*.sqlite` file directly inside the system temp directory before Laravel boots. An empty value is rejected, and existing SQLite files must resolve inside that directory with exactly one filesystem link. - `phpunit.xml` fixes testing env, `MAIL_MAILER=array`, `SESSION_DRIVER=array`, `CACHE_STORE=array` with legacy `CACHE_DRIVER=file`, sync queue, and service-source warning restrictions. - Use shared fixture helpers before creating local copies: `standardResources()`, `createNodeData()`, `createConfigOption()`, and per-file helpers such as configured products/cart items. - Common fakes are `Mockery` service/container bindings, `Http::fake()` with `Http::preventStrayRequests()` for panel calls, `Notification::fake()`, `Event::fake()`, `Log::spy()`, `Config::set()`, and `Gate::policy()`. diff --git a/tests/Feature/AvailabilityApiTest.php b/tests/Feature/AvailabilityApiTest.php index 34a9786..54504a2 100644 --- a/tests/Feature/AvailabilityApiTest.php +++ b/tests/Feature/AvailabilityApiTest.php @@ -78,6 +78,28 @@ public function test_has_capacity_true_when_all_resources_positive(): void 'Customer availability response must not expose node-level data'); } + public function test_customer_failure_response_does_not_expose_internal_exception(): void + { + /** @var User $user */ + $user = User::factory()->create(); + + $nodeService = Mockery::mock(NodeSelectionService::class); + $nodeService->shouldReceive('getMaxAvailable') + ->once() + ->with(1) + ->andThrow(new \RuntimeException('panel-internal-host:8080 failed')); + $this->app->instance(NodeSelectionService::class, $nodeService); + $this->app->instance(ResourceCalculationService::class, Mockery::mock(ResourceCalculationService::class)); + + $response = $this->actingAs($user)->getJson('/api/dynamic-pterodactyl/availability/1'); + + $response->assertStatus(500)->assertExactJson([ + 'success' => false, + 'message' => 'Failed to fetch availability', + ]); + $this->assertStringNotContainsString('panel-internal-host', $response->getContent()); + } + private function bindAvailabilityServices(array $maxAvailable): void { $nodeService = Mockery::mock(NodeSelectionService::class); diff --git a/tests/TestDatabaseGuard.php b/tests/TestDatabaseGuard.php index 12ed6e0..eda2b4f 100644 --- a/tests/TestDatabaseGuard.php +++ b/tests/TestDatabaseGuard.php @@ -6,11 +6,15 @@ final class TestDatabaseGuard { public static function allows(string $database, string $connection, string $environment): bool { + if ($environment !== 'testing') { + return false; + } + if ($database === 'paymenter_test') { - return true; + return in_array($connection, ['mysql', 'mariadb'], true); } - if ($environment !== 'testing' || $connection !== 'sqlite') { + if ($connection !== 'sqlite') { return false; } @@ -21,9 +25,40 @@ public static function allows(string $database, string $connection, string $envi $databaseDirectory = realpath(dirname($database)); $temporaryDirectory = realpath(sys_get_temp_dir()); - return $databaseDirectory !== false - && $temporaryDirectory !== false - && strcasecmp($databaseDirectory, $temporaryDirectory) === 0 - && preg_match('/^dynamic-pterodactyl-test-[a-z0-9-]+\.sqlite$/i', basename($database)) === 1; + if ($databaseDirectory === false + || $temporaryDirectory === false + ) { + return false; + } + + $pathsMatch = PHP_OS_FAMILY === 'Windows' + ? strcasecmp($databaseDirectory, $temporaryDirectory) === 0 + : $databaseDirectory === $temporaryDirectory; + + if (! $pathsMatch + || preg_match('/^dynamic-pterodactyl-test-[a-z0-9-]+\.sqlite$/i', basename($database)) !== 1 + ) { + return false; + } + + if (! file_exists($database)) { + return true; + } + + $resolvedDatabase = realpath($database); + $fileStatus = @stat($database); + + return ! is_link($database) + && $resolvedDatabase !== false + && self::pathsEqual(dirname($resolvedDatabase), $temporaryDirectory) + && is_array($fileStatus) + && ($fileStatus['nlink'] ?? 0) === 1; + } + + private static function pathsEqual(string $left, string $right): bool + { + return PHP_OS_FAMILY === 'Windows' + ? strcasecmp($left, $right) === 0 + : $left === $right; } } diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index 62f2474..c846bf8 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -220,6 +220,28 @@ public function test_location_availability_groups_included_servers_by_node(): vo $this->assertSame(['memory' => 7168, 'cpu' => 350, 'disk' => 46080], $result['nodes'][0]['available']); } + public function test_location_availability_ignores_malformed_included_relationships(): void + { + Http::fake([ + 'panel.example.com/*' => Http::response([ + 'object' => 'location', + 'attributes' => [ + 'id' => 1, + 'relationships' => [ + 'nodes' => ['data' => 'not-an-array'], + 'servers' => ['data' => [['attributes' => 'not-an-array']]], + ], + ], + ], 200), + ]); + + $result = $this->service->getLocationAvailability(1); + + Http::assertSentCount(1); + $this->assertSame([], $result['nodes']); + $this->assertSame(['memory' => 0, 'cpu' => 0, 'disk' => 0], $result['max_available']); + } + public function test_snapshot_with_single_location_single_node(): void { $calls = 0; diff --git a/tests/Unit/TestDatabaseGuardTest.php b/tests/Unit/TestDatabaseGuardTest.php index 18e721c..ffd2bc2 100644 --- a/tests/Unit/TestDatabaseGuardTest.php +++ b/tests/Unit/TestDatabaseGuardTest.php @@ -40,4 +40,30 @@ public function test_rejects_empty_database_name_before_application_boot(): void { $this->assertFalse(TestDatabaseGuard::allows('', 'sqlite', 'testing')); } + + public function test_rejects_paymenter_test_database_outside_testing_environment(): void + { + $this->assertFalse(TestDatabaseGuard::allows('paymenter_test', 'mysql', 'production')); + $this->assertTrue(TestDatabaseGuard::allows('paymenter_test', 'mariadb', 'testing')); + } + + public function test_rejects_hard_linked_sqlite_alias(): void + { + $suffix = bin2hex(random_bytes(6)); + $sourceDirectory = sys_get_temp_dir().DIRECTORY_SEPARATOR.'database-guard-source-'.$suffix; + $source = $sourceDirectory.DIRECTORY_SEPARATOR.'valuable.sqlite'; + $alias = sys_get_temp_dir().DIRECTORY_SEPARATOR.'dynamic-pterodactyl-test-hardlink-'.$suffix.'.sqlite'; + + mkdir($sourceDirectory); + file_put_contents($source, 'must not be treated as a disposable test database'); + $this->assertTrue(link($source, $alias)); + + try { + $this->assertFalse(TestDatabaseGuard::allows($alias, 'sqlite', 'testing')); + } finally { + unlink($alias); + unlink($source); + rmdir($sourceDirectory); + } + } } From c34192ea4aa521dc8ee59ede45b38a0459c2fed8 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 20:08:02 +1000 Subject: [PATCH 09/95] docs: remove final per-node availability remnants --- .../Architecture Overview/Companion Extension Pattern.md | 6 ++---- .../Service Layer Design/Resource Calculation Service.md | 1 - .../Service Layer Design/Service Layer Design.md | 2 +- .qoder/repowiki/en/content/Core Services/Core Services.md | 4 ++-- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md b/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md index 8936ad7..3d9d4df 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md @@ -202,10 +202,8 @@ participant Ptero as "Pterodactyl API" participant DB as "Reservations DB" Controller->>RSC : getLocationAvailability(locationId) RSC->>Ptero : GET /locations/{id}?include=nodes,servers -Ptero-->>RSC : nodes -loop For each node -RSC->>Ptero : GET node with servers -Ptero-->>RSC : servers +Ptero-->>RSC : location with nodes and servers +loop For each included node RSC->>DB : SUM pending reservations for node DB-->>RSC : reserved amounts RSC->>RSC : compute available = effective - allocated - reserved diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md index bebc0fd..6e286a2 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md @@ -88,7 +88,6 @@ C->>A : GET /availability/{locationId} A->>N : getMaxAvailable(locationId) N->>S : getLocationAvailability(locationId) S->>P : GET /locations/{id}?include=nodes,servers -S->>P : GET node + servers (include=servers) S->>D : SUM pending reservations (node_id, pending, not expired) S-->>N : Node availability arrays N-->>A : Max available per resource diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md index ef0ac3c..dc68163 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md @@ -95,7 +95,7 @@ participant P as "Pterodactyl API" C->>A : GET /availability/{locationId} A->>N : getMaxAvailable(locationId) N->>R : getLocationAvailability(locationId) -R->>P : GET nodes + servers (paginated) +R->>P : GET /locations/{id}?include=nodes,servers P-->>R : JSON payload R-->>N : location availability N-->>A : max_available diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index 6f89f0e..81f72ed 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -105,7 +105,7 @@ Client->>RSvc : create(productId, locationId, resources, ...) RSvc->>DB : lockForUpdate(pending reservations) RSvc->>NSvc : selectBestNode(locationId, resources) NSvc->>RCSvc : getLocationAvailability(locationId) -RCSvc->>PT : GET nodes/servers (real-time) +RCSvc->>PT : GET /locations/{id}?include=nodes,servers PT-->>RCSvc : node/server data RCSvc-->>NSvc : availability + totals NSvc-->>RSvc : selected node or null @@ -485,4 +485,4 @@ NextCfg --> Done(["End"]) **Diagram sources** - [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) - [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) \ No newline at end of file +- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) From 77c9807e6c258649f40319a6cee14014df2860fa Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 20:16:38 +1000 Subject: [PATCH 10/95] test: atomically claim standalone sqlite database --- DECISIONS.md | 2 +- tests/AGENTS.md | 6 ++-- tests/LaravelTestCase.php | 23 +++++++++++- tests/TestDatabaseGuard.php | 53 ++++++++++++++++++---------- tests/Unit/TestDatabaseGuardTest.php | 38 ++++++++++---------- tests/bootstrap.php | 4 +-- 6 files changed, 82 insertions(+), 44 deletions(-) diff --git a/DECISIONS.md b/DECISIONS.md index 097e606..8d184be 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -244,7 +244,7 @@ Unit coverage accepted for dp-06. The full Filament-action lifecycle end-to-end ### 6. Test Isolation Mandate (dp-13, Apr 2026) -Extension phpunit MUST set `CACHE_STORE=array`, `SESSION_DRIVER=array`, `QUEUE_CONNECTION=sync`, `MAIL_MAILER=array`, `BCRYPT_ROUNDS=4`, `PULSE_ENABLED=false`, `TELESCOPE_ENABLED=false` — mirroring the root `phpunit.xml`. Failure to do so risks polluting the shared Redis/file cache on a development host, corrupting the settings key read by running web workers. This caused a production outage on 2026-04-23. The `bootstrap.php` guard provides a second line of defence: it requires `APP_ENV=testing` and accepts only `paymenter_test`, `:memory:`, or a strictly named `dynamic-pterodactyl-test-*.sqlite` file directly inside the system temp directory. Existing SQLite files must resolve inside that directory and have exactly one filesystem link, preventing symlink and hard-link aliases. Empty database names and arbitrary SQLite paths remain forbidden. See `incidents.md` for forensics. +Extension phpunit MUST set `CACHE_STORE=array`, `SESSION_DRIVER=array`, `QUEUE_CONNECTION=sync`, `MAIL_MAILER=array`, `BCRYPT_ROUNDS=4`, `PULSE_ENABLED=false`, `TELESCOPE_ENABLED=false` — mirroring the root `phpunit.xml`. Failure to do so risks polluting the shared Redis/file cache on a development host, corrupting the settings key read by running web workers. This caused a production outage on 2026-04-23. The `bootstrap.php` guard provides a second line of defence: it requires `APP_ENV=testing` and accepts only `paymenter_test`, `:memory:`, or a new `dynamic-pterodactyl-test-*/database.sqlite` path under the system temp directory. File-backed SQLite is claimed by atomically creating its private directory and database and holding the exclusive file handle; every pre-existing path is rejected. Empty database names, arbitrary paths, and filename-based trust are forbidden. See `incidents.md` for forensics. ### 7. SetupWizard Atomicity Contract (dp-13, Apr 2026) diff --git a/tests/AGENTS.md b/tests/AGENTS.md index 83760d1..218408f 100644 --- a/tests/AGENTS.md +++ b/tests/AGENTS.md @@ -23,7 +23,7 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p | Task | Start at | Notes | |---|---|---| -| Harness boot / DB safety | `bootstrap.php`, `TestDatabaseGuard.php`, `../phpunit.xml` | `paymenter_test`, `:memory:`, or a strictly named disposable SQLite file in the system temp directory is enforced before app boot | +| Harness boot / DB safety | `bootstrap.php`, `TestDatabaseGuard.php`, `../phpunit.xml` | `paymenter_test`, `:memory:`, or an atomically claimed new `dynamic-pterodactyl-test-*/database.sqlite` path is enforced before app boot | | Lightweight service seam | `TestCase.php` | Mockery cleanup, `createPricingConfig()`, `createNodeData()`, `standardResources()` | | App-backed test seam | `LaravelTestCase.php` | Paymenter kernel boot, `createConfigOption()`, slider defaults, node fixtures | | Reservation state / audits | `Unit/ReservationServiceTest.php` | Mixes facade mocks and real DB assertions under transactions | @@ -40,7 +40,7 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p - Any DB-writing test must use `Illuminate\Foundation\Testing\DatabaseTransactions`; this includes DB-backed `Unit/` tests and all current API feature tests. - Feature API tests must `require __DIR__ . '/../../routes/api.php';` in `setUp()` because extension routes are loaded manually by `DynamicPterodactyl::boot()` at runtime. - For schedule assertions, boot the extension in the test and inspect `app(Schedule::class)->events()`; no local Job/Command classes exist. -- The bootstrap refuses unsafe databases and requires `APP_ENV=testing`. `DB_DATABASE` must be `paymenter_test`, `:memory:`, or a `dynamic-pterodactyl-test-*.sqlite` file directly inside the system temp directory before Laravel boots. An empty value is rejected, and existing SQLite files must resolve inside that directory with exactly one filesystem link. +- The bootstrap refuses unsafe databases and requires `APP_ENV=testing`. `DB_DATABASE` must be `paymenter_test`, `:memory:`, or `dynamic-pterodactyl-test-*/database.sqlite` under the system temp directory. For file-backed SQLite, the guard atomically creates a new private directory and database, holds the exclusive file handle, and rejects every pre-existing directory or database. `LaravelTestCase` migrates a newly claimed standalone SQLite database on its first application boot. - `phpunit.xml` fixes testing env, `MAIL_MAILER=array`, `SESSION_DRIVER=array`, `CACHE_STORE=array` with legacy `CACHE_DRIVER=file`, sync queue, and service-source warning restrictions. - Use shared fixture helpers before creating local copies: `standardResources()`, `createNodeData()`, `createConfigOption()`, and per-file helpers such as configured products/cart items. - Common fakes are `Mockery` service/container bindings, `Http::fake()` with `Http::preventStrayRequests()` for panel calls, `Notification::fake()`, `Event::fake()`, `Log::spy()`, `Config::set()`, and `Gate::policy()`. @@ -55,7 +55,7 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p - Do not put app/factory/facade tests on raw `TestCase` except the existing separate-process `AlertService` facade isolation seam. - Do not claim `Unit/` files are all pure units; several intentionally boot Laravel and write DB rows. - Do not duplicate root command blocks, generic PHPUnit advice, or project-wide anti-patterns here. -- Do not broaden the database guard beyond `paymenter_test`, `:memory:`, or the validated disposable system-temp SQLite naming contract. +- Do not broaden the database guard beyond `paymenter_test`, `:memory:`, or an atomically claimed new system-temp SQLite directory. Never infer disposability from a pre-existing filename. - Do not add live Pterodactyl network calls; fake panel HTTP explicitly and prevent strays when testing capacity reads. - Do not expose or assert full reservation tokens in audit payloads; assert `token_prefix` behavior. - Current direct coverage gaps to watch: `CartItemCreatedListener`, `ServiceCreatedListener`, `PricingController::getConfig()`, and `AuditLogService` retrieval methods. diff --git a/tests/LaravelTestCase.php b/tests/LaravelTestCase.php index c6446ab..25e5000 100644 --- a/tests/LaravelTestCase.php +++ b/tests/LaravelTestCase.php @@ -7,6 +7,8 @@ abstract class LaravelTestCase extends BaseTestCase { + private static bool $standaloneSqliteMigrated = false; + /** * Creates the application. */ @@ -26,7 +28,26 @@ public function createApplication() } $app = require $bootstrap; - $app->make(Kernel::class)->bootstrap(); + $kernel = $app->make(Kernel::class); + $kernel->bootstrap(); + + $database = getenv('DB_DATABASE') ?: ($_ENV['DB_DATABASE'] ?? ''); + if (! self::$standaloneSqliteMigrated + && (getenv('DB_CONNECTION') ?: ($_ENV['DB_CONNECTION'] ?? '')) === 'sqlite' + && $database !== ':memory:' + ) { + $kernel->call('migrate', [ + '--database' => 'sqlite', + '--force' => true, + ]); + $kernel->call('migrate', [ + '--database' => 'sqlite', + '--path' => dirname(__DIR__).'/database/migrations', + '--realpath' => true, + '--force' => true, + ]); + self::$standaloneSqliteMigrated = true; + } return $app; } diff --git a/tests/TestDatabaseGuard.php b/tests/TestDatabaseGuard.php index eda2b4f..7420301 100644 --- a/tests/TestDatabaseGuard.php +++ b/tests/TestDatabaseGuard.php @@ -4,7 +4,10 @@ final class TestDatabaseGuard { - public static function allows(string $database, string $connection, string $environment): bool + /** @var array */ + private static array $claimedDatabaseHandles = []; + + public static function claim(string $database, string $connection, string $environment): bool { if ($environment !== 'testing') { return false; @@ -22,37 +25,51 @@ public static function allows(string $database, string $connection, string $envi return true; } - $databaseDirectory = realpath(dirname($database)); + return self::claimDisposableSqliteDatabase($database); + } + + private static function claimDisposableSqliteDatabase(string $database): bool + { + $databaseDirectory = dirname($database); + $directoryParent = realpath(dirname($databaseDirectory)); $temporaryDirectory = realpath(sys_get_temp_dir()); - if ($databaseDirectory === false + if ($directoryParent === false || $temporaryDirectory === false + || ! self::pathsEqual($directoryParent, $temporaryDirectory) + || preg_match('/^dynamic-pterodactyl-test-[a-z0-9-]+$/i', basename($databaseDirectory)) !== 1 + || basename($database) !== 'database.sqlite' ) { return false; } - $pathsMatch = PHP_OS_FAMILY === 'Windows' - ? strcasecmp($databaseDirectory, $temporaryDirectory) === 0 - : $databaseDirectory === $temporaryDirectory; + if (! @mkdir($databaseDirectory, 0700)) { + return false; + } + + $resolvedDirectory = realpath($databaseDirectory); + if ($resolvedDirectory === false || ! self::pathsEqual(dirname($resolvedDirectory), $temporaryDirectory)) { + @rmdir($databaseDirectory); - if (! $pathsMatch - || preg_match('/^dynamic-pterodactyl-test-[a-z0-9-]+\.sqlite$/i', basename($database)) !== 1 - ) { return false; } - if (! file_exists($database)) { - return true; + $handle = @fopen($database, 'x+b'); + $fileStatus = $handle === false ? false : fstat($handle); + + if ($handle === false || ! is_array($fileStatus) || ($fileStatus['nlink'] ?? 0) !== 1) { + if (is_resource($handle)) { + fclose($handle); + } + @unlink($database); + @rmdir($databaseDirectory); + + return false; } - $resolvedDatabase = realpath($database); - $fileStatus = @stat($database); + self::$claimedDatabaseHandles[$database] = $handle; - return ! is_link($database) - && $resolvedDatabase !== false - && self::pathsEqual(dirname($resolvedDatabase), $temporaryDirectory) - && is_array($fileStatus) - && ($fileStatus['nlink'] ?? 0) === 1; + return true; } private static function pathsEqual(string $left, string $right): bool diff --git a/tests/Unit/TestDatabaseGuardTest.php b/tests/Unit/TestDatabaseGuardTest.php index ffd2bc2..eb94cc5 100644 --- a/tests/Unit/TestDatabaseGuardTest.php +++ b/tests/Unit/TestDatabaseGuardTest.php @@ -16,7 +16,7 @@ public function test_rejects_existing_arbitrary_sqlite_database(): void rename($temporaryFile, $database); try { - $this->assertFalse(TestDatabaseGuard::allows($database, 'sqlite', 'testing')); + $this->assertFalse(TestDatabaseGuard::claim($database, 'sqlite', 'testing')); } finally { unlink($database); } @@ -24,46 +24,46 @@ public function test_rejects_existing_arbitrary_sqlite_database(): void public function test_allows_disposable_sqlite_database_in_system_temp_directory(): void { - $database = sys_get_temp_dir().DIRECTORY_SEPARATOR.'dynamic-pterodactyl-test-example.sqlite'; + $database = sys_get_temp_dir().DIRECTORY_SEPARATOR.'dynamic-pterodactyl-test-'.bin2hex(random_bytes(6)) + .DIRECTORY_SEPARATOR.'database.sqlite'; - $this->assertTrue(TestDatabaseGuard::allows($database, 'sqlite', 'testing')); + $this->assertTrue(TestDatabaseGuard::claim($database, 'sqlite', 'testing')); + $this->assertFileExists($database); } public function test_rejects_disposable_name_outside_system_temp_directory(): void { - $database = dirname(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'dynamic-pterodactyl-test-example.sqlite'; + $database = dirname(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'dynamic-pterodactyl-test-example' + .DIRECTORY_SEPARATOR.'database.sqlite'; - $this->assertFalse(TestDatabaseGuard::allows($database, 'sqlite', 'testing')); + $this->assertFalse(TestDatabaseGuard::claim($database, 'sqlite', 'testing')); } public function test_rejects_empty_database_name_before_application_boot(): void { - $this->assertFalse(TestDatabaseGuard::allows('', 'sqlite', 'testing')); + $this->assertFalse(TestDatabaseGuard::claim('', 'sqlite', 'testing')); } public function test_rejects_paymenter_test_database_outside_testing_environment(): void { - $this->assertFalse(TestDatabaseGuard::allows('paymenter_test', 'mysql', 'production')); - $this->assertTrue(TestDatabaseGuard::allows('paymenter_test', 'mariadb', 'testing')); + $this->assertFalse(TestDatabaseGuard::claim('paymenter_test', 'mysql', 'production')); + $this->assertTrue(TestDatabaseGuard::claim('paymenter_test', 'mariadb', 'testing')); } - public function test_rejects_hard_linked_sqlite_alias(): void + public function test_rejects_pre_existing_disposable_database_directory(): void { $suffix = bin2hex(random_bytes(6)); - $sourceDirectory = sys_get_temp_dir().DIRECTORY_SEPARATOR.'database-guard-source-'.$suffix; - $source = $sourceDirectory.DIRECTORY_SEPARATOR.'valuable.sqlite'; - $alias = sys_get_temp_dir().DIRECTORY_SEPARATOR.'dynamic-pterodactyl-test-hardlink-'.$suffix.'.sqlite'; + $databaseDirectory = sys_get_temp_dir().DIRECTORY_SEPARATOR.'dynamic-pterodactyl-test-existing-'.$suffix; + $database = $databaseDirectory.DIRECTORY_SEPARATOR.'database.sqlite'; - mkdir($sourceDirectory); - file_put_contents($source, 'must not be treated as a disposable test database'); - $this->assertTrue(link($source, $alias)); + mkdir($databaseDirectory); + file_put_contents($database, 'must not be treated as a disposable test database'); try { - $this->assertFalse(TestDatabaseGuard::allows($alias, 'sqlite', 'testing')); + $this->assertFalse(TestDatabaseGuard::claim($database, 'sqlite', 'testing')); } finally { - unlink($alias); - unlink($source); - rmdir($sourceDirectory); + unlink($database); + rmdir($databaseDirectory); } } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index c3c14d8..a43b01f 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -26,13 +26,13 @@ $connection = getenv('DB_CONNECTION') ?: ($_ENV['DB_CONNECTION'] ?? ''); $appEnvironment = getenv('APP_ENV') ?: ($_ENV['APP_ENV'] ?? ''); -if (! \Paymenter\Extensions\Others\DynamicPterodactyl\Tests\TestDatabaseGuard::allows( +if (! \Paymenter\Extensions\Others\DynamicPterodactyl\Tests\TestDatabaseGuard::claim( $db, $connection, $appEnvironment, )) { fwrite(STDERR, "ABORT: phpunit would run against DB_DATABASE='$db'. " - . "Expected 'paymenter_test', ':memory:', or a disposable dynamic-pterodactyl-test-*.sqlite file in the system temp directory. " + . "Expected 'paymenter_test', ':memory:', or a new system-temp dynamic-pterodactyl-test-*/database.sqlite path claimed by this process. " . "See .sisyphus/notepads/dp-11-authorization-surface-reduction/incidents.md.\n"); exit(2); } From 2a9c3a4ba9aa6489e7cb85e36f3588338befcc6a Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 20:16:45 +1000 Subject: [PATCH 11/95] fix: fail closed on malformed availability payloads --- Services/ResourceCalculationService.php | 30 ++++++++++--- tests/Unit/ResourceCalculationServiceTest.php | 44 ++++++++++++++++--- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index f99bacd..2f89946 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -231,8 +231,8 @@ private function fetchNodesInLocation(int $locationId): array ['include' => 'nodes,servers'] ); - $nodesData = $this->extractRelationshipData($response, 'nodes'); - $serversData = $this->extractRelationshipData($response, 'servers'); + $nodesData = $this->requireRelationshipData($response, 'nodes'); + $serversData = $this->requireRelationshipData($response, 'servers'); // Group servers by node_id for per-node allocation accounting $serversByNode = []; @@ -241,8 +241,8 @@ private function fetchNodesInLocation(int $locationId): array ? $server['attributes'] : null; $nodeId = $attributes['node'] ?? null; - if ($nodeId === null) { - continue; + if ($nodeId === null || ! is_array($attributes['limits'] ?? null)) { + throw new \RuntimeException('Pterodactyl API returned an invalid included server payload.'); } $serversByNode[$nodeId][] = $attributes; } @@ -253,7 +253,7 @@ private function fetchNodesInLocation(int $locationId): array ? $node['attributes'] : null; if ($attrs === null || ! isset($attrs['id'], $attrs['name'], $attrs['fqdn'], $attrs['memory'], $attrs['disk'])) { - continue; + throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); } $nodeId = $attrs['id']; $nodes[] = [ @@ -425,6 +425,26 @@ private function extractRelationshipData(array $payload, string $relationship): return []; } + private function requireRelationshipData(array $payload, string $relationship): array + { + $attributes = is_array($payload['attributes'] ?? null) ? $payload['attributes'] : []; + $relationships = is_array($attributes['relationships'] ?? null) + ? $attributes['relationships'] + : []; + $entry = is_array($relationships[$relationship] ?? null) + ? $relationships[$relationship] + : null; + + if ($entry === null || ! is_array($entry['data'] ?? null)) { + throw new \RuntimeException(sprintf( + 'Pterodactyl API returned an invalid %s relationship payload.', + $relationship + )); + } + + return $entry['data']; + } + private function emptyClusterSnapshot(): array { return [ diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index c846bf8..11d1e80 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -220,7 +220,7 @@ public function test_location_availability_groups_included_servers_by_node(): vo $this->assertSame(['memory' => 7168, 'cpu' => 350, 'disk' => 46080], $result['nodes'][0]['available']); } - public function test_location_availability_ignores_malformed_included_relationships(): void + public function test_location_availability_rejects_malformed_included_relationships(): void { Http::fake([ 'panel.example.com/*' => Http::response([ @@ -235,11 +235,45 @@ public function test_location_availability_ignores_malformed_included_relationsh ], 200), ]); - $result = $this->service->getLocationAvailability(1); + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('invalid nodes relationship payload'); - Http::assertSentCount(1); - $this->assertSame([], $result['nodes']); - $this->assertSame(['memory' => 0, 'cpu' => 0, 'disk' => 0], $result['max_available']); + $this->service->getLocationAvailability(1); + } + + public function test_location_availability_rejects_malformed_included_server_limits(): void + { + Http::fake([ + 'panel.example.com/*' => Http::response([ + 'object' => 'location', + 'attributes' => [ + 'id' => 1, + 'relationships' => [ + 'nodes' => ['data' => [[ + 'attributes' => [ + 'id' => 5, + 'name' => 'Node 5', + 'fqdn' => 'node-5.example.com', + 'memory' => 8192, + 'disk' => 51200, + 'cpu_threads' => 4, + ], + ]]], + 'servers' => ['data' => [[ + 'attributes' => [ + 'node' => 5, + 'limits' => 'not-an-array', + ], + ]]], + ], + ], + ], 200), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('invalid included server payload'); + + $this->service->getLocationAvailability(1); } public function test_snapshot_with_single_location_single_node(): void From d21bcfcb0f0b6889c66bac0953309c2d516fb520 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 20:47:16 +1000 Subject: [PATCH 12/95] test: generate isolated standalone sqlite database --- DECISIONS.md | 2 +- tests/AGENTS.md | 6 +-- tests/TestDatabaseGuard.php | 60 ++++++++++++++++++---------- tests/Unit/TestDatabaseGuardTest.php | 18 ++++----- tests/bootstrap.php | 14 +++++-- 5 files changed, 63 insertions(+), 37 deletions(-) diff --git a/DECISIONS.md b/DECISIONS.md index 8d184be..c6fd1ba 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -244,7 +244,7 @@ Unit coverage accepted for dp-06. The full Filament-action lifecycle end-to-end ### 6. Test Isolation Mandate (dp-13, Apr 2026) -Extension phpunit MUST set `CACHE_STORE=array`, `SESSION_DRIVER=array`, `QUEUE_CONNECTION=sync`, `MAIL_MAILER=array`, `BCRYPT_ROUNDS=4`, `PULSE_ENABLED=false`, `TELESCOPE_ENABLED=false` — mirroring the root `phpunit.xml`. Failure to do so risks polluting the shared Redis/file cache on a development host, corrupting the settings key read by running web workers. This caused a production outage on 2026-04-23. The `bootstrap.php` guard provides a second line of defence: it requires `APP_ENV=testing` and accepts only `paymenter_test`, `:memory:`, or a new `dynamic-pterodactyl-test-*/database.sqlite` path under the system temp directory. File-backed SQLite is claimed by atomically creating its private directory and database and holding the exclusive file handle; every pre-existing path is rejected. Empty database names, arbitrary paths, and filename-based trust are forbidden. See `incidents.md` for forensics. +Extension phpunit MUST set `CACHE_STORE=array`, `SESSION_DRIVER=array`, `QUEUE_CONNECTION=sync`, `MAIL_MAILER=array`, `BCRYPT_ROUNDS=4`, `PULSE_ENABLED=false`, `TELESCOPE_ENABLED=false` — mirroring the root `phpunit.xml`. Failure to do so risks polluting the shared Redis/file cache on a development host, corrupting the settings key read by running web workers. This caused a production outage on 2026-04-23. The `bootstrap.php` guard provides a second line of defence: it requires `APP_ENV=testing` and accepts only `paymenter_test`, `:memory:`, or the `:temporary:` sentinel. The sentinel generates an unpredictable private system-temp directory, atomically creates the SQLite database, holds the exclusive file handle, and replaces `DB_DATABASE` before Paymenter boots. Caller-supplied SQLite paths, empty database names, and filename-based trust are forbidden. See `incidents.md` for forensics. ### 7. SetupWizard Atomicity Contract (dp-13, Apr 2026) diff --git a/tests/AGENTS.md b/tests/AGENTS.md index 218408f..11b8b06 100644 --- a/tests/AGENTS.md +++ b/tests/AGENTS.md @@ -23,7 +23,7 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p | Task | Start at | Notes | |---|---|---| -| Harness boot / DB safety | `bootstrap.php`, `TestDatabaseGuard.php`, `../phpunit.xml` | `paymenter_test`, `:memory:`, or an atomically claimed new `dynamic-pterodactyl-test-*/database.sqlite` path is enforced before app boot | +| Harness boot / DB safety | `bootstrap.php`, `TestDatabaseGuard.php`, `../phpunit.xml` | `paymenter_test`, `:memory:`, or the `:temporary:` sentinel for an internally generated SQLite database is enforced before app boot | | Lightweight service seam | `TestCase.php` | Mockery cleanup, `createPricingConfig()`, `createNodeData()`, `standardResources()` | | App-backed test seam | `LaravelTestCase.php` | Paymenter kernel boot, `createConfigOption()`, slider defaults, node fixtures | | Reservation state / audits | `Unit/ReservationServiceTest.php` | Mixes facade mocks and real DB assertions under transactions | @@ -40,7 +40,7 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p - Any DB-writing test must use `Illuminate\Foundation\Testing\DatabaseTransactions`; this includes DB-backed `Unit/` tests and all current API feature tests. - Feature API tests must `require __DIR__ . '/../../routes/api.php';` in `setUp()` because extension routes are loaded manually by `DynamicPterodactyl::boot()` at runtime. - For schedule assertions, boot the extension in the test and inspect `app(Schedule::class)->events()`; no local Job/Command classes exist. -- The bootstrap refuses unsafe databases and requires `APP_ENV=testing`. `DB_DATABASE` must be `paymenter_test`, `:memory:`, or `dynamic-pterodactyl-test-*/database.sqlite` under the system temp directory. For file-backed SQLite, the guard atomically creates a new private directory and database, holds the exclusive file handle, and rejects every pre-existing directory or database. `LaravelTestCase` migrates a newly claimed standalone SQLite database on its first application boot. +- The bootstrap refuses unsafe databases and requires `APP_ENV=testing`. `DB_DATABASE` must be `paymenter_test`, `:memory:`, or the `:temporary:` sentinel. For `:temporary:`, the guard generates an unpredictable private directory under the system temp directory, atomically creates the database, holds the exclusive file handle, and replaces `DB_DATABASE` before Paymenter boots. User-supplied SQLite paths are never accepted. `LaravelTestCase` migrates the claimed database on first application boot. - `phpunit.xml` fixes testing env, `MAIL_MAILER=array`, `SESSION_DRIVER=array`, `CACHE_STORE=array` with legacy `CACHE_DRIVER=file`, sync queue, and service-source warning restrictions. - Use shared fixture helpers before creating local copies: `standardResources()`, `createNodeData()`, `createConfigOption()`, and per-file helpers such as configured products/cart items. - Common fakes are `Mockery` service/container bindings, `Http::fake()` with `Http::preventStrayRequests()` for panel calls, `Notification::fake()`, `Event::fake()`, `Log::spy()`, `Config::set()`, and `Gate::policy()`. @@ -55,7 +55,7 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p - Do not put app/factory/facade tests on raw `TestCase` except the existing separate-process `AlertService` facade isolation seam. - Do not claim `Unit/` files are all pure units; several intentionally boot Laravel and write DB rows. - Do not duplicate root command blocks, generic PHPUnit advice, or project-wide anti-patterns here. -- Do not broaden the database guard beyond `paymenter_test`, `:memory:`, or an atomically claimed new system-temp SQLite directory. Never infer disposability from a pre-existing filename. +- Do not broaden the database guard beyond `paymenter_test`, `:memory:`, or the internally generated `:temporary:` workflow. Never accept a caller-supplied SQLite path or infer disposability from a filename. - Do not add live Pterodactyl network calls; fake panel HTTP explicitly and prevent strays when testing capacity reads. - Do not expose or assert full reservation tokens in audit payloads; assert `token_prefix` behavior. - Current direct coverage gaps to watch: `CartItemCreatedListener`, `ServiceCreatedListener`, `PricingController::getConfig()`, and `AuditLogService` retrieval methods. diff --git a/tests/TestDatabaseGuard.php b/tests/TestDatabaseGuard.php index 7420301..772fbaa 100644 --- a/tests/TestDatabaseGuard.php +++ b/tests/TestDatabaseGuard.php @@ -7,53 +7,54 @@ final class TestDatabaseGuard /** @var array */ private static array $claimedDatabaseHandles = []; - public static function claim(string $database, string $connection, string $environment): bool + private static bool $cleanupRegistered = false; + + public static function claim(string $database, string $connection, string $environment): ?string { if ($environment !== 'testing') { - return false; + return null; } if ($database === 'paymenter_test') { - return in_array($connection, ['mysql', 'mariadb'], true); + return in_array($connection, ['mysql', 'mariadb'], true) ? $database : null; } if ($connection !== 'sqlite') { - return false; + return null; } if ($database === ':memory:') { - return true; + return $database; + } + + if ($database !== ':temporary:') { + return null; } - return self::claimDisposableSqliteDatabase($database); + return self::claimDisposableSqliteDatabase(); } - private static function claimDisposableSqliteDatabase(string $database): bool + private static function claimDisposableSqliteDatabase(): ?string { - $databaseDirectory = dirname($database); - $directoryParent = realpath(dirname($databaseDirectory)); $temporaryDirectory = realpath(sys_get_temp_dir()); - - if ($directoryParent === false - || $temporaryDirectory === false - || ! self::pathsEqual($directoryParent, $temporaryDirectory) - || preg_match('/^dynamic-pterodactyl-test-[a-z0-9-]+$/i', basename($databaseDirectory)) !== 1 - || basename($database) !== 'database.sqlite' - ) { - return false; + if ($temporaryDirectory === false) { + return null; } + $databaseDirectory = $temporaryDirectory.DIRECTORY_SEPARATOR + .'dynamic-pterodactyl-test-'.bin2hex(random_bytes(16)); if (! @mkdir($databaseDirectory, 0700)) { - return false; + return null; } $resolvedDirectory = realpath($databaseDirectory); if ($resolvedDirectory === false || ! self::pathsEqual(dirname($resolvedDirectory), $temporaryDirectory)) { @rmdir($databaseDirectory); - return false; + return null; } + $database = $resolvedDirectory.DIRECTORY_SEPARATOR.'database.sqlite'; $handle = @fopen($database, 'x+b'); $fileStatus = $handle === false ? false : fstat($handle); @@ -64,12 +65,29 @@ private static function claimDisposableSqliteDatabase(string $database): bool @unlink($database); @rmdir($databaseDirectory); - return false; + return null; } self::$claimedDatabaseHandles[$database] = $handle; + if (! self::$cleanupRegistered) { + register_shutdown_function(static function (): void { + self::releaseClaims(); + }); + self::$cleanupRegistered = true; + } + + return $database; + } + + private static function releaseClaims(): void + { + foreach (self::$claimedDatabaseHandles as $database => $handle) { + fclose($handle); + @unlink($database); + @rmdir(dirname($database)); + } - return true; + self::$claimedDatabaseHandles = []; } private static function pathsEqual(string $left, string $right): bool diff --git a/tests/Unit/TestDatabaseGuardTest.php b/tests/Unit/TestDatabaseGuardTest.php index eb94cc5..48a3970 100644 --- a/tests/Unit/TestDatabaseGuardTest.php +++ b/tests/Unit/TestDatabaseGuardTest.php @@ -16,7 +16,7 @@ public function test_rejects_existing_arbitrary_sqlite_database(): void rename($temporaryFile, $database); try { - $this->assertFalse(TestDatabaseGuard::claim($database, 'sqlite', 'testing')); + $this->assertNull(TestDatabaseGuard::claim($database, 'sqlite', 'testing')); } finally { unlink($database); } @@ -24,10 +24,10 @@ public function test_rejects_existing_arbitrary_sqlite_database(): void public function test_allows_disposable_sqlite_database_in_system_temp_directory(): void { - $database = sys_get_temp_dir().DIRECTORY_SEPARATOR.'dynamic-pterodactyl-test-'.bin2hex(random_bytes(6)) - .DIRECTORY_SEPARATOR.'database.sqlite'; + $database = TestDatabaseGuard::claim(':temporary:', 'sqlite', 'testing'); - $this->assertTrue(TestDatabaseGuard::claim($database, 'sqlite', 'testing')); + $this->assertIsString($database); + $this->assertStringStartsWith(realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR, $database); $this->assertFileExists($database); } @@ -36,18 +36,18 @@ public function test_rejects_disposable_name_outside_system_temp_directory(): vo $database = dirname(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'dynamic-pterodactyl-test-example' .DIRECTORY_SEPARATOR.'database.sqlite'; - $this->assertFalse(TestDatabaseGuard::claim($database, 'sqlite', 'testing')); + $this->assertNull(TestDatabaseGuard::claim($database, 'sqlite', 'testing')); } public function test_rejects_empty_database_name_before_application_boot(): void { - $this->assertFalse(TestDatabaseGuard::claim('', 'sqlite', 'testing')); + $this->assertNull(TestDatabaseGuard::claim('', 'sqlite', 'testing')); } public function test_rejects_paymenter_test_database_outside_testing_environment(): void { - $this->assertFalse(TestDatabaseGuard::claim('paymenter_test', 'mysql', 'production')); - $this->assertTrue(TestDatabaseGuard::claim('paymenter_test', 'mariadb', 'testing')); + $this->assertNull(TestDatabaseGuard::claim('paymenter_test', 'mysql', 'production')); + $this->assertSame('paymenter_test', TestDatabaseGuard::claim('paymenter_test', 'mariadb', 'testing')); } public function test_rejects_pre_existing_disposable_database_directory(): void @@ -60,7 +60,7 @@ public function test_rejects_pre_existing_disposable_database_directory(): void file_put_contents($database, 'must not be treated as a disposable test database'); try { - $this->assertFalse(TestDatabaseGuard::claim($database, 'sqlite', 'testing')); + $this->assertNull(TestDatabaseGuard::claim($database, 'sqlite', 'testing')); } finally { unlink($database); rmdir($databaseDirectory); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index a43b01f..fea94a7 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -26,16 +26,24 @@ $connection = getenv('DB_CONNECTION') ?: ($_ENV['DB_CONNECTION'] ?? ''); $appEnvironment = getenv('APP_ENV') ?: ($_ENV['APP_ENV'] ?? ''); -if (! \Paymenter\Extensions\Others\DynamicPterodactyl\Tests\TestDatabaseGuard::claim( +$claimedDatabase = \Paymenter\Extensions\Others\DynamicPterodactyl\Tests\TestDatabaseGuard::claim( $db, $connection, $appEnvironment, -)) { +); + +if ($claimedDatabase === null) { fwrite(STDERR, "ABORT: phpunit would run against DB_DATABASE='$db'. " - . "Expected 'paymenter_test', ':memory:', or a new system-temp dynamic-pterodactyl-test-*/database.sqlite path claimed by this process. " + . "Expected 'paymenter_test', ':memory:', or ':temporary:' for an internally generated standalone SQLite database. " . "See .sisyphus/notepads/dp-11-authorization-surface-reduction/incidents.md.\n"); exit(2); } +if ($claimedDatabase !== $db) { + putenv("DB_DATABASE={$claimedDatabase}"); + $_ENV['DB_DATABASE'] = $claimedDatabase; + $_SERVER['DB_DATABASE'] = $claimedDatabase; +} + require __DIR__ . '/TestCase.php'; require __DIR__ . '/LaravelTestCase.php'; From 6ebc7ce7bc21846792f615dd1de6faeeeb8edb7f Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 20:47:16 +1000 Subject: [PATCH 13/95] fix: reject incomplete capacity payloads --- Services/ResourceCalculationService.php | 195 ++++++++++++------ tests/Unit/ResourceCalculationServiceTest.php | 146 ++++++++++++- 2 files changed, 263 insertions(+), 78 deletions(-) diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index 2f89946..3ed524b 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -234,30 +234,26 @@ private function fetchNodesInLocation(int $locationId): array $nodesData = $this->requireRelationshipData($response, 'nodes'); $serversData = $this->requireRelationshipData($response, 'servers'); - // Group servers by node_id for per-node allocation accounting + $nodesById = []; + foreach ($nodesData as $node) { + $attributes = $this->requireNodeAttributes($node); + $nodesById[$attributes['id']] = $attributes; + } + $serversByNode = []; foreach ($serversData as $server) { - $attributes = is_array($server) && is_array($server['attributes'] ?? null) - ? $server['attributes'] - : null; - $nodeId = $attributes['node'] ?? null; - if ($nodeId === null || ! is_array($attributes['limits'] ?? null)) { - throw new \RuntimeException('Pterodactyl API returned an invalid included server payload.'); + $attributes = $this->requireServerAttributes($server); + $nodeId = $attributes['node']; + if (! array_key_exists($nodeId, $nodesById)) { + throw new \RuntimeException('Pterodactyl API returned a server for an unknown included node.'); } $serversByNode[$nodeId][] = $attributes; } $nodes = []; - foreach ($nodesData as $node) { - $attrs = is_array($node) && is_array($node['attributes'] ?? null) - ? $node['attributes'] - : null; - if ($attrs === null || ! isset($attrs['id'], $attrs['name'], $attrs['fqdn'], $attrs['memory'], $attrs['disk'])) { - throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); - } - $nodeId = $attrs['id']; + foreach ($nodesById as $nodeId => $attributes) { $nodes[] = [ - 'node' => $attrs, + 'node' => $attributes, 'servers' => $serversByNode[$nodeId] ?? [], ]; } @@ -267,17 +263,19 @@ private function fetchNodesInLocation(int $locationId): array private function buildNodeAvailabilityFromServers(array $node, array $servers, array $pendingReservations): array { + $this->validateNodeAttributes($node); + $allocated = ['memory' => 0, 'cpu' => 0, 'disk' => 0]; foreach ($servers as $server) { - $limits = is_array($server['limits'] ?? null) ? $server['limits'] : []; - $allocated['memory'] += $limits['memory'] ?? 0; - $allocated['cpu'] += $limits['cpu'] ?? 0; - $allocated['disk'] += $limits['disk'] ?? 0; + $this->validateServerAttributes($server); + $allocated['memory'] += $server['limits']['memory']; + $allocated['cpu'] += $server['limits']['cpu']; + $allocated['disk'] += $server['limits']['disk']; } $effectiveMemory = $node['memory'] * (1 + ($node['memory_overallocate'] ?? 0) / 100); $effectiveDisk = $node['disk'] * (1 + ($node['disk_overallocate'] ?? 0) / 100); - $effectiveCpu = ($node['cpu_threads'] ?? 4) * 100; + $effectiveCpu = $node['cpu_threads'] * 100; $available = [ 'memory' => max(0, (int) $effectiveMemory - $allocated['memory'] - $pendingReservations['memory']), @@ -336,43 +334,52 @@ private function fetchClusterNodes(): array private function fetchClusterNodesWithIncludedServers(): array { - return \collect($this->pterodactylGetPaginatedData('/api/application/nodes', [ + $nodes = []; + foreach ($this->pterodactylGetPaginatedData('/api/application/nodes', [ 'include' => 'servers', 'per_page' => 100, - ]))->mapWithKeys(function ($node) { - $attributes = $node['attributes'] ?? []; + ]) as $node) { + $attributes = $this->requireNodeAttributes($node); + $servers = []; + foreach ($this->requireRelationshipData($node, 'servers') as $server) { + $serverAttributes = $this->requireServerAttributes($server); + if ($serverAttributes['node'] !== $attributes['id']) { + throw new \RuntimeException('Pterodactyl API returned a server for an unexpected node.'); + } + $servers[] = $serverAttributes; + } - return [ - $attributes['id'] => [ - 'node' => $attributes, - 'location_id' => $attributes['location_id'], - 'servers' => \collect($this->extractRelationshipData($node, 'servers')) - ->map(fn ($server) => $server['attributes']) - ->toArray(), - ], + $nodes[$attributes['id']] = [ + 'node' => $attributes, + 'location_id' => $attributes['location_id'], + 'servers' => $servers, ]; - })->toArray(); + } + + return $nodes; } private function fetchClusterNodesFromServerIndex(): array { - $nodes = \collect($this->pterodactylGetPaginatedData('/api/application/nodes', ['per_page' => 100])) - ->mapWithKeys(fn ($node) => [ - $node['attributes']['id'] => [ - 'node' => $node['attributes'], - 'location_id' => $node['attributes']['location_id'], - 'servers' => [], - ], - ]) - ->toArray(); + $nodes = []; + foreach ($this->pterodactylGetPaginatedData('/api/application/nodes', ['per_page' => 100]) as $node) { + $attributes = $this->requireNodeAttributes($node); + $nodes[$attributes['id']] = [ + 'node' => $attributes, + 'location_id' => $attributes['location_id'], + 'servers' => [], + ]; + } foreach ($this->pterodactylGetPaginatedData('/api/application/servers', ['per_page' => 100]) as $server) { - $attributes = $server['attributes'] ?? []; - $nodeId = $attributes['node'] ?? null; + $attributes = $this->requireServerAttributes($server); + $nodeId = $attributes['node']; - if ($nodeId !== null && array_key_exists($nodeId, $nodes)) { - $nodes[$nodeId]['servers'][] = $attributes; + if (! array_key_exists($nodeId, $nodes)) { + throw new \RuntimeException('Pterodactyl API returned a server for an unknown node.'); } + + $nodes[$nodeId]['servers'][] = $attributes; } return $nodes; @@ -385,7 +392,10 @@ private function pterodactylGetPaginatedData(string $path, array $query = []): a while (true) { $payload = $this->pterodactylGet($path, array_merge($query, ['page' => $page])); - $data = array_merge($data, $payload['data'] ?? []); + if (! is_array($payload['data'] ?? null)) { + throw new \RuntimeException('Pterodactyl API returned an invalid paginated data payload.'); + } + $data = array_merge($data, $payload['data']); $pagination = $payload['meta']['pagination'] ?? null; if (! is_array($pagination)) { @@ -405,26 +415,6 @@ private function pterodactylGetPaginatedData(string $path, array $query = []): a return $data; } - private function extractRelationshipData(array $payload, string $relationship): array - { - $attributes = is_array($payload['attributes'] ?? null) ? $payload['attributes'] : []; - $relationshipSets = [ - is_array($attributes['relationships'] ?? null) ? $attributes['relationships'] : [], - is_array($payload['relationships'] ?? null) ? $payload['relationships'] : [], - ]; - - foreach ($relationshipSets as $relationships) { - $entry = is_array($relationships[$relationship] ?? null) - ? $relationships[$relationship] - : []; - if (is_array($entry['data'] ?? null)) { - return $entry['data']; - } - } - - return []; - } - private function requireRelationshipData(array $payload, string $relationship): array { $attributes = is_array($payload['attributes'] ?? null) ? $payload['attributes'] : []; @@ -445,6 +435,77 @@ private function requireRelationshipData(array $payload, string $relationship): return $entry['data']; } + private function requireNodeAttributes(mixed $payload): array + { + $attributes = is_array($payload) && is_array($payload['attributes'] ?? null) + ? $payload['attributes'] + : null; + if ($attributes === null) { + throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); + } + + $this->validateNodeAttributes($attributes); + $attributes['id'] = (int) $attributes['id']; + $attributes['location_id'] = (int) $attributes['location_id']; + + return $attributes; + } + + private function requireServerAttributes(mixed $payload): array + { + $attributes = is_array($payload) && is_array($payload['attributes'] ?? null) + ? $payload['attributes'] + : null; + if ($attributes === null) { + throw new \RuntimeException('Pterodactyl API returned an invalid included server payload.'); + } + + $this->validateServerAttributes($attributes); + $attributes['node'] = (int) $attributes['node']; + + return $attributes; + } + + private function validateNodeAttributes(array $attributes): void + { + foreach (['id', 'location_id'] as $field) { + if (filter_var($attributes[$field] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) === false) { + throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); + } + } + + foreach (['memory', 'disk', 'cpu_threads'] as $field) { + if (! is_numeric($attributes[$field] ?? null) || (float) $attributes[$field] <= 0) { + throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); + } + } + + if (! is_string($attributes['name'] ?? null) || $attributes['name'] === '' + || ! is_string($attributes['fqdn'] ?? null) || $attributes['fqdn'] === '') { + throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); + } + + foreach (['memory_overallocate', 'disk_overallocate'] as $field) { + if (array_key_exists($field, $attributes) && ! is_numeric($attributes[$field])) { + throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); + } + } + } + + private function validateServerAttributes(array $attributes): void + { + if (filter_var($attributes['node'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) === false + || ! is_array($attributes['limits'] ?? null)) { + throw new \RuntimeException('Pterodactyl API returned an invalid included server payload.'); + } + + foreach (['memory', 'cpu', 'disk'] as $field) { + if (! is_numeric($attributes['limits'][$field] ?? null) || (float) $attributes['limits'][$field] < 0) { + throw new \RuntimeException('Pterodactyl API returned an invalid included server payload.'); + } + } + } + private function emptyClusterSnapshot(): array { return [ diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index 11d1e80..20c4f70 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -204,6 +204,7 @@ public function test_location_availability_groups_included_servers_by_node(): vo ['node' => 5, 'memory' => 1024, 'cpu' => 50, 'disk' => 5120], ['node' => 6, 'memory' => 4096, 'cpu' => 200, 'disk' => 20480], ], + additionalNodeIds: [6], )); $result = $this->service->getLocationAvailability(1); @@ -218,6 +219,8 @@ public function test_location_availability_groups_included_servers_by_node(): vo }); $this->assertSame(['memory' => 1024, 'cpu' => 50, 'disk' => 5120], $result['nodes'][0]['allocated']); $this->assertSame(['memory' => 7168, 'cpu' => 350, 'disk' => 46080], $result['nodes'][0]['available']); + $this->assertSame(['memory' => 4096, 'cpu' => 200, 'disk' => 20480], $result['nodes'][1]['allocated']); + $this->assertSame(['memory' => 4096, 'cpu' => 200, 'disk' => 30720], $result['nodes'][1]['available']); } public function test_location_availability_rejects_malformed_included_relationships(): void @@ -252,6 +255,7 @@ public function test_location_availability_rejects_malformed_included_server_lim 'nodes' => ['data' => [[ 'attributes' => [ 'id' => 5, + 'location_id' => 1, 'name' => 'Node 5', 'fqdn' => 'node-5.example.com', 'memory' => 8192, @@ -276,6 +280,125 @@ public function test_location_availability_rejects_malformed_included_server_lim $this->service->getLocationAvailability(1); } + public function test_location_availability_rejects_incomplete_included_server_limits(): void + { + Http::fake($this->availabilityHttpFake( + nodeId: 5, + locationId: 1, + totalMemory: 8192, + totalDisk: 51200, + totalCpuThreads: 4, + servers: [['node' => 5, 'memory' => 1024, 'cpu' => 50]], + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('invalid included server payload'); + + $this->service->getLocationAvailability(1); + } + + public function test_location_availability_rejects_negative_included_server_limits(): void + { + Http::fake($this->availabilityHttpFake( + nodeId: 5, + locationId: 1, + totalMemory: 8192, + totalDisk: 51200, + totalCpuThreads: 4, + servers: [['node' => 5, 'memory' => 1024, 'cpu' => -1, 'disk' => 5120]], + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('invalid included server payload'); + + $this->service->getLocationAvailability(1); + } + + public function test_location_availability_rejects_server_for_unknown_node(): void + { + Http::fake($this->availabilityHttpFake( + nodeId: 5, + locationId: 1, + totalMemory: 8192, + totalDisk: 51200, + totalCpuThreads: 4, + servers: [['node' => 6, 'memory' => 1024, 'cpu' => 50, 'disk' => 5120]], + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('unknown included node'); + + $this->service->getLocationAvailability(1); + } + + public function test_location_availability_rejects_node_without_cpu_threads(): void + { + Http::fake([ + 'panel.example.com/*' => Http::response([ + 'attributes' => [ + 'relationships' => [ + 'nodes' => ['data' => [[ + 'attributes' => [ + 'id' => 5, + 'location_id' => 1, + 'name' => 'Node 5', + 'fqdn' => 'node-5.example.com', + 'memory' => 8192, + 'disk' => 51200, + ], + ]]], + 'servers' => ['data' => []], + ], + ], + ], 200), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('invalid included node payload'); + + $this->service->getLocationAvailability(1); + } + + public function test_snapshot_falls_back_when_included_servers_relationship_is_missing(): void + { + $calls = 0; + $node = $this->nodeWithServersPayload(1, 1, 'Node 1', []); + unset($node['attributes']['relationships']); + + Http::fake(function ($request) use (&$calls, $node) { + $calls++; + $url = $request->url(); + + if (str_contains($url, '/api/application/locations')) { + return Http::response([ + 'data' => [['attributes' => ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']]], + ], 200); + } + + if (str_contains($url, '/api/application/nodes')) { + return Http::response(['data' => [$node]], 200); + } + + if (str_contains($url, '/api/application/servers')) { + return Http::response([ + 'data' => [[ + 'attributes' => [ + 'node' => 1, + 'limits' => ['memory' => 1024, 'cpu' => 50, 'disk' => 5120], + ], + ]], + ], 200); + } + + return Http::response([], 404); + }); + + $snapshot = $this->service->buildClusterSnapshot(); + + $this->assertSame(['memory' => 1024, 'cpu' => 50, 'disk' => 5120], $snapshot['nodes'][1]['allocated']); + $this->assertSame(4, $calls); + } + public function test_snapshot_with_single_location_single_node(): void { $calls = 0; @@ -446,9 +569,10 @@ private function availabilityHttpFake( int $totalDisk, int $totalCpuThreads, array $servers = [], + array $additionalNodeIds = [], ): callable { - return function ($request) use ($nodeId, $locationId, $totalMemory, $totalDisk, $totalCpuThreads, $servers) { + return function ($request) use ($nodeId, $locationId, $totalMemory, $totalDisk, $totalCpuThreads, $servers, $additionalNodeIds) { $url = $request->url(); $query = []; parse_str(parse_url($url, PHP_URL_QUERY) ?? '', $query); @@ -463,13 +587,13 @@ private function availabilityHttpFake( 'relationships' => [ 'nodes' => [ 'object' => 'list', - 'data' => [[ + 'data' => array_map(fn (int $includedNodeId) => [ 'object' => 'node', 'attributes' => [ - 'id' => $nodeId, + 'id' => $includedNodeId, 'location_id' => $locationId, - 'name' => 'Node '.$nodeId, - 'fqdn' => 'node-'.$nodeId.'.example.com', + 'name' => 'Node '.$includedNodeId, + 'fqdn' => 'node-'.$includedNodeId.'.example.com', 'memory' => $totalMemory, 'disk' => $totalDisk, 'cpu_threads' => $totalCpuThreads, @@ -481,7 +605,7 @@ private function availabilityHttpFake( 'disk' => 0, ], ], - ]], + ], array_merge([$nodeId], $additionalNodeIds)), ], 'servers' => [ 'object' => 'list', @@ -490,11 +614,11 @@ private function availabilityHttpFake( 'attributes' => [ 'id' => ($server['node'] * 100) + $index, 'node' => $server['node'], - 'limits' => [ - 'memory' => $server['memory'], - 'cpu' => $server['cpu'], - 'disk' => $server['disk'], - ], + 'limits' => array_intersect_key($server, [ + 'memory' => true, + 'cpu' => true, + 'disk' => true, + ]), ], ], $servers, array_keys($servers)), ], From ec7ba5e0af9361a52d8d94141595ea2149c3d7a9 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 20:47:16 +1000 Subject: [PATCH 14/95] docs: align wiki and reconciliation status --- .../en/content/API Reference/API Reference.md | 4 ++-- .../Availability Endpoints.md | 8 ++++---- .../Public API Endpoints/Public API Endpoints.md | 6 +++--- .qoder/repowiki/en/content/Deployment.md | 1 + .qoder/repowiki/en/content/Testing.md | 16 ++++++++-------- PROGRESS.md | 8 ++++++-- 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index 7df432e..aed692e 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -145,7 +145,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - has_capacity: boolean - resource_capacity: object with memory/cpu/disk booleans - Errors: - - 500: failure to fetch availability (includes message and error fields) + - 500: failure to fetch availability (returns only the generic message; exception details are reported server-side) - GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes - Auth: web + auth + admin @@ -519,4 +519,4 @@ The Dynamic Pterodactyl extension exposes a focused set of APIs for availability - Validate inputs on the client side but rely on server-side validation and authorization. - Do not expose node-level details to customers; use admin endpoints for internal tools only. -[No sources needed since this section provides general guidance] \ No newline at end of file +[No sources needed since this section provides general guidance] diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md index cb1a8b0..be4f35e 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md @@ -138,7 +138,7 @@ A-->>C : {success, data : {location_id, max_memory, max_cpu, max_disk, node_coun - cpu: boolean (true if max_cpu > 0) - disk: boolean (true if max_disk > 0) - Error responses: - - On exceptions during processing, returns success: false with message and error fields, HTTP 500. + - On exceptions during processing, returns HTTP 500 with `success: false` and the generic message `Failed to fetch availability`. Exception details are reported server-side and are not returned to customers. Request examples - Basic request: @@ -181,9 +181,9 @@ Request examples Error handling - Invalid or missing locationId: - - If the location does not exist or cannot be resolved, upstream errors propagate through services and are caught by the controller, returning success: false with a generic message and error details. + - If the location does not exist or cannot be resolved, the controller returns `success: false` with a generic message and reports the underlying exception server-side. - Pterodactyl API failures: - - Network timeouts, connection errors, or non-2xx responses result in exceptions thrown by the service layer and surfaced as success: false with a descriptive message. + - Network timeouts, connection errors, or non-2xx responses result in a generic `success: false` response; upstream details remain in server-side diagnostics. - Rate limiting exceeded: - Requests beyond 30 per minute receive a standard throttle response from the framework's throttle middleware. @@ -342,7 +342,7 @@ Common issues and how they manifest: - Invalid location: - If the locationId does not resolve to any nodes, the service may return empty aggregates; the controller wraps errors into a consistent failure response. - Pterodactyl API errors: - - Network timeouts, connection failures, or non-2xx responses cause exceptions in the service layer; these are caught and returned as success: false with a message and error details. + - Network timeouts, connection failures, or non-2xx responses are caught, reported server-side, and returned as `success: false` with only the generic availability failure message. - Unexpected payload: - Malformed or non-JSON responses from Pterodactyl are treated as errors and logged for diagnostics. - **Enhanced**: Security validation failures: diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md index bd52b11..b242479 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md @@ -132,7 +132,7 @@ Example request: - Success response example: - { "success": true, "data": { "location_id": 1, "max_memory": 1000, "max_cpu": 100, "max_disk": 1000, "node_count": 3, "has_capacity": true, "resource_capacity": { "memory": true, "cpu": true, "disk": true } } } - Error response example: - - { "success": false, "message": "Failed to fetch availability", "error": "" } + - { "success": false, "message": "Failed to fetch availability" } Implementation notes: - Uses NodeSelectionService to compute maximum available resources per location. @@ -345,7 +345,7 @@ Common issues and resolutions: - You do not own the reservation and are not an admin. Error response patterns: -- Availability failures: 500 with generic message and optional error details. +- Availability failures: 500 with a generic message only; exception details are reported server-side. - Pricing failures: 500 with generic message; detailed error only when debug is enabled. - Reservation failures: 422 for validation/runtime errors; 404 for not found; 403 for unauthorized. @@ -359,4 +359,4 @@ Error response patterns: ## Conclusion The Dynamic Pterodactyl public API provides secure, rate-limited endpoints for checking availability, calculating dynamic pricing, and managing short-lived resource reservations during checkout. It exposes only aggregate capacity to customers, preserving node-level details for administrative use. The design emphasizes idempotency, real-time accuracy, and robust authorization to ensure safe and reliable integration with the checkout flow. -[No sources needed since this section summarizes without analyzing specific files] \ No newline at end of file +[No sources needed since this section summarizes without analyzing specific files] diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index 3c9b177..1e73cb7 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -144,6 +144,7 @@ Operational requirements: - Scheduler must be running to execute cleanup and alert checks. - Database must support transactions and pessimistic locking. - Network access to the Pterodactyl Panel API must be allowed from the Paymenter host. +- Node payloads must provide a numeric `cpu_threads` capacity value; missing or malformed node/server capacity fields fail closed instead of advertising unverified capacity. **Section sources** - [DynamicPterodactyl.php:48-75](file://DynamicPterodactyl.php#L48-L75) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index db5cc12..769a3f4 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -100,7 +100,7 @@ Key components under test: ## Architecture Overview The testing architecture isolates external dependencies and enforces deterministic environments: - phpunit.xml forces array cache/session/queue and sync queue. -- tests/bootstrap.php aborts if DB_DATABASE is not a test database. +- tests/bootstrap.php requires `APP_ENV=testing` and accepts only `paymenter_test`, `:memory:`, or the `:temporary:` sentinel. The sentinel generates and atomically claims an unpredictable private SQLite path before Paymenter boots; caller-supplied SQLite paths are rejected. - Feature tests load routes and use DatabaseTransactions to keep state isolated per test. - Unit tests mock or fake HTTP and DB interactions to avoid real calls. @@ -124,7 +124,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](file://phpunit.xml#L28-L41) -- [tests/bootstrap.php:11-17](file://tests/bootstrap.php#L11-L17) +- [tests/bootstrap.php:23-48](file://tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](file://tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -329,7 +329,7 @@ ALS --> NOTIF["Notifications"] ## Troubleshooting Guide Common issues and fixes: -- Running against wrong database: tests/bootstrap.php aborts unless DB_DATABASE is paymenter_test or :memory:. Ensure your environment matches. +- Running against wrong database: tests/bootstrap.php aborts unless `DB_DATABASE` is `paymenter_test`, `:memory:`, or `:temporary:`. Use `:temporary:` for standalone SQLite; do not provide a filesystem path. - Stray HTTP requests: enable Http::preventStrayRequests() in setUp to catch unexpected network calls during unit tests. - Stale global state in alert tests: use #[RunTestsInSeparateProcesses] and #[PreserveGlobalState(false)] to isolate Facade containers. - Authorization failures: ensure Gate policies are registered and actors are set up correctly in tests. @@ -341,7 +341,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:11-17](file://tests/bootstrap.php#L11-L17) +- [tests/bootstrap.php:23-48](file://tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](file://tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](file://tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](file://tests/Unit/ReservationServiceTest.php#L29-L46) @@ -354,7 +354,7 @@ The test suite provides robust coverage across service logic, API endpoints, and ## Appendices ### How to Run the Test Suite -- Ensure DB_DATABASE is set to paymenter_test or :memory:. +- Set `DB_DATABASE` to `paymenter_test`, `:memory:`, or `:temporary:`. The standalone `:temporary:` database is generated, migrated on first application boot, and cleaned up at process shutdown. - Use the outer Paymenter vendor PHPUnit binary as configured by the project. - Run unit tests: vendor/bin/phpunit --testsuite=Unit - Run feature tests: vendor/bin/phpunit --testsuite=Feature @@ -363,7 +363,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](file://phpunit.xml#L13-L20) - [phpunit.xml:28-41](file://phpunit.xml#L28-L41) -- [tests/bootstrap.php:11-17](file://tests/bootstrap.php#L11-L17) +- [tests/bootstrap.php:23-48](file://tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -398,14 +398,14 @@ The test suite provides robust coverage across service logic, API endpoints, and ### Test Database Setup and Fixtures - Database isolation: - phpunit.xml sets DB_CONNECTION and DB_DATABASE for tests. - - tests/bootstrap.php enforces test database guard. + - tests/bootstrap.php enforces the test database guard and atomically owns any standalone SQLite path before use. - Fixtures: - Create minimal required records (products, config options, carts, cart items) within tests. - Use factories where available; otherwise insert raw rows via DB facade. **Section sources** - [phpunit.xml:34-36](file://phpunit.xml#L34-L36) -- [tests/bootstrap.php:11-17](file://tests/bootstrap.php#L11-L17) +- [tests/bootstrap.php:23-48](file://tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](file://tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/PROGRESS.md b/PROGRESS.md index 32dc190..91edf33 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -72,11 +72,15 @@ All dp-NN backlog items are implemented. The active reconciliation is staged on **Status**: Panel changes are preserved on the reconciliation branch; Qoder Wiki pages are migrated to GitHub Wiki and refreshed for the final batched location API flow. **Current file**: PROGRESS.md **Next action**: Complete exact-SHA review, then merge draft PR #23 when approved. Resume Mutagen only as a separately authorized deployment step. -**Blockers**: None +**Blockers**: PR #22 overlaps this reconciliation and must be rebased after PR #23; merging it unchanged would restore superseded test-guard and error-response behavior. No CI checks are configured on PR #23. ### This Session's Changes: -1. dp-19 — direct commits on `dynamic-slider` (extension) and `dynamic-slider/1.4.7` (outer Paymenter). +1. Preserved the dp-20 panel close-out without restoring obsolete deployment guidance. +2. Reconciled the location availability path to one `locations/{id}?include=nodes,servers` request and fail-closed capacity parsing. +3. Replaced caller-selected SQLite test paths with the internally generated `:temporary:` database workflow. +4. Migrated the retained Qoder page set to GitHub Wiki and synchronized API, deployment, and testing contracts. +5. Published draft PR #23 for exact-SHA review; Mutagen deployment remains paused. --- From 2f7566545fd7b6e5f129905d098b88de6d12cc99 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 21:16:22 +1000 Subject: [PATCH 15/95] test: isolate sqlite without filesystem paths --- DECISIONS.md | 2 +- tests/AGENTS.md | 6 +-- tests/TestDatabaseGuard.php | 59 ++++++---------------------- tests/Unit/TestDatabaseGuardTest.php | 25 ++++++++++-- 4 files changed, 38 insertions(+), 54 deletions(-) diff --git a/DECISIONS.md b/DECISIONS.md index c6fd1ba..fca4bc1 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -244,7 +244,7 @@ Unit coverage accepted for dp-06. The full Filament-action lifecycle end-to-end ### 6. Test Isolation Mandate (dp-13, Apr 2026) -Extension phpunit MUST set `CACHE_STORE=array`, `SESSION_DRIVER=array`, `QUEUE_CONNECTION=sync`, `MAIL_MAILER=array`, `BCRYPT_ROUNDS=4`, `PULSE_ENABLED=false`, `TELESCOPE_ENABLED=false` — mirroring the root `phpunit.xml`. Failure to do so risks polluting the shared Redis/file cache on a development host, corrupting the settings key read by running web workers. This caused a production outage on 2026-04-23. The `bootstrap.php` guard provides a second line of defence: it requires `APP_ENV=testing` and accepts only `paymenter_test`, `:memory:`, or the `:temporary:` sentinel. The sentinel generates an unpredictable private system-temp directory, atomically creates the SQLite database, holds the exclusive file handle, and replaces `DB_DATABASE` before Paymenter boots. Caller-supplied SQLite paths, empty database names, and filename-based trust are forbidden. See `incidents.md` for forensics. +Extension phpunit MUST set `CACHE_STORE=array`, `SESSION_DRIVER=array`, `QUEUE_CONNECTION=sync`, `MAIL_MAILER=array`, `BCRYPT_ROUNDS=4`, `PULSE_ENABLED=false`, `TELESCOPE_ENABLED=false` — mirroring the root `phpunit.xml`. Failure to do so risks polluting the shared Redis/file cache on a development host, corrupting the settings key read by running web workers. This caused a production outage on 2026-04-23. The `bootstrap.php` guard provides a second line of defence: it requires `APP_ENV=testing` and accepts only `paymenter_test`, `:memory:`, or the `:temporary:` sentinel. The sentinel creates an unpredictable process-private named in-memory SQLite database, retains an anchor PDO connection for its lifetime, and replaces `DB_DATABASE` before Paymenter boots. There is no filesystem pathname to substitute. Caller-supplied SQLite paths or URI names and empty database names are forbidden. See `incidents.md` for forensics. ### 7. SetupWizard Atomicity Contract (dp-13, Apr 2026) diff --git a/tests/AGENTS.md b/tests/AGENTS.md index 11b8b06..a7f59c7 100644 --- a/tests/AGENTS.md +++ b/tests/AGENTS.md @@ -23,7 +23,7 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p | Task | Start at | Notes | |---|---|---| -| Harness boot / DB safety | `bootstrap.php`, `TestDatabaseGuard.php`, `../phpunit.xml` | `paymenter_test`, `:memory:`, or the `:temporary:` sentinel for an internally generated SQLite database is enforced before app boot | +| Harness boot / DB safety | `bootstrap.php`, `TestDatabaseGuard.php`, `../phpunit.xml` | `paymenter_test`, `:memory:`, or the `:temporary:` sentinel for an internally generated named in-memory SQLite database is enforced before app boot | | Lightweight service seam | `TestCase.php` | Mockery cleanup, `createPricingConfig()`, `createNodeData()`, `standardResources()` | | App-backed test seam | `LaravelTestCase.php` | Paymenter kernel boot, `createConfigOption()`, slider defaults, node fixtures | | Reservation state / audits | `Unit/ReservationServiceTest.php` | Mixes facade mocks and real DB assertions under transactions | @@ -40,7 +40,7 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p - Any DB-writing test must use `Illuminate\Foundation\Testing\DatabaseTransactions`; this includes DB-backed `Unit/` tests and all current API feature tests. - Feature API tests must `require __DIR__ . '/../../routes/api.php';` in `setUp()` because extension routes are loaded manually by `DynamicPterodactyl::boot()` at runtime. - For schedule assertions, boot the extension in the test and inspect `app(Schedule::class)->events()`; no local Job/Command classes exist. -- The bootstrap refuses unsafe databases and requires `APP_ENV=testing`. `DB_DATABASE` must be `paymenter_test`, `:memory:`, or the `:temporary:` sentinel. For `:temporary:`, the guard generates an unpredictable private directory under the system temp directory, atomically creates the database, holds the exclusive file handle, and replaces `DB_DATABASE` before Paymenter boots. User-supplied SQLite paths are never accepted. `LaravelTestCase` migrates the claimed database on first application boot. +- The bootstrap refuses unsafe databases and requires `APP_ENV=testing`. `DB_DATABASE` must be `paymenter_test`, `:memory:`, or the `:temporary:` sentinel. For `:temporary:`, the guard generates an unpredictable process-private named in-memory SQLite database, retains an anchor PDO connection, and replaces `DB_DATABASE` before Paymenter boots. User-supplied SQLite paths and URI names are never accepted. `LaravelTestCase` migrates the shared in-memory database on first application boot; process teardown discards it. - `phpunit.xml` fixes testing env, `MAIL_MAILER=array`, `SESSION_DRIVER=array`, `CACHE_STORE=array` with legacy `CACHE_DRIVER=file`, sync queue, and service-source warning restrictions. - Use shared fixture helpers before creating local copies: `standardResources()`, `createNodeData()`, `createConfigOption()`, and per-file helpers such as configured products/cart items. - Common fakes are `Mockery` service/container bindings, `Http::fake()` with `Http::preventStrayRequests()` for panel calls, `Notification::fake()`, `Event::fake()`, `Log::spy()`, `Config::set()`, and `Gate::policy()`. @@ -55,7 +55,7 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p - Do not put app/factory/facade tests on raw `TestCase` except the existing separate-process `AlertService` facade isolation seam. - Do not claim `Unit/` files are all pure units; several intentionally boot Laravel and write DB rows. - Do not duplicate root command blocks, generic PHPUnit advice, or project-wide anti-patterns here. -- Do not broaden the database guard beyond `paymenter_test`, `:memory:`, or the internally generated `:temporary:` workflow. Never accept a caller-supplied SQLite path or infer disposability from a filename. +- Do not broaden the database guard beyond `paymenter_test`, `:memory:`, or the internally generated `:temporary:` workflow. Never accept a caller-supplied SQLite path or named-memory URI. - Do not add live Pterodactyl network calls; fake panel HTTP explicitly and prevent strays when testing capacity reads. - Do not expose or assert full reservation tokens in audit payloads; assert `token_prefix` behavior. - Current direct coverage gaps to watch: `CartItemCreatedListener`, `ServiceCreatedListener`, `PricingController::getConfig()`, and `AuditLogService` retrieval methods. diff --git a/tests/TestDatabaseGuard.php b/tests/TestDatabaseGuard.php index 772fbaa..76c8b42 100644 --- a/tests/TestDatabaseGuard.php +++ b/tests/TestDatabaseGuard.php @@ -4,8 +4,8 @@ final class TestDatabaseGuard { - /** @var array */ - private static array $claimedDatabaseHandles = []; + /** @var array */ + private static array $claimedDatabaseConnections = []; private static bool $cleanupRegistered = false; @@ -31,44 +31,22 @@ public static function claim(string $database, string $connection, string $envir return null; } - return self::claimDisposableSqliteDatabase(); + return self::claimIsolatedSqliteDatabase(); } - private static function claimDisposableSqliteDatabase(): ?string + private static function claimIsolatedSqliteDatabase(): ?string { - $temporaryDirectory = realpath(sys_get_temp_dir()); - if ($temporaryDirectory === false) { - return null; - } - - $databaseDirectory = $temporaryDirectory.DIRECTORY_SEPARATOR - .'dynamic-pterodactyl-test-'.bin2hex(random_bytes(16)); - if (! @mkdir($databaseDirectory, 0700)) { - return null; - } - - $resolvedDirectory = realpath($databaseDirectory); - if ($resolvedDirectory === false || ! self::pathsEqual(dirname($resolvedDirectory), $temporaryDirectory)) { - @rmdir($databaseDirectory); - - return null; - } - - $database = $resolvedDirectory.DIRECTORY_SEPARATOR.'database.sqlite'; - $handle = @fopen($database, 'x+b'); - $fileStatus = $handle === false ? false : fstat($handle); - - if ($handle === false || ! is_array($fileStatus) || ($fileStatus['nlink'] ?? 0) !== 1) { - if (is_resource($handle)) { - fclose($handle); - } - @unlink($database); - @rmdir($databaseDirectory); + $database = 'file:dynamic-pterodactyl-test-'.bin2hex(random_bytes(16)).'?mode=memory&cache=shared'; + try { + $connection = new \PDO('sqlite:'.$database, null, null, [ + \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, + ]); + } catch (\PDOException) { return null; } - self::$claimedDatabaseHandles[$database] = $handle; + self::$claimedDatabaseConnections[$database] = $connection; if (! self::$cleanupRegistered) { register_shutdown_function(static function (): void { self::releaseClaims(); @@ -81,19 +59,6 @@ private static function claimDisposableSqliteDatabase(): ?string private static function releaseClaims(): void { - foreach (self::$claimedDatabaseHandles as $database => $handle) { - fclose($handle); - @unlink($database); - @rmdir(dirname($database)); - } - - self::$claimedDatabaseHandles = []; - } - - private static function pathsEqual(string $left, string $right): bool - { - return PHP_OS_FAMILY === 'Windows' - ? strcasecmp($left, $right) === 0 - : $left === $right; + self::$claimedDatabaseConnections = []; } } diff --git a/tests/Unit/TestDatabaseGuardTest.php b/tests/Unit/TestDatabaseGuardTest.php index 48a3970..f94ecb2 100644 --- a/tests/Unit/TestDatabaseGuardTest.php +++ b/tests/Unit/TestDatabaseGuardTest.php @@ -22,13 +22,32 @@ public function test_rejects_existing_arbitrary_sqlite_database(): void } } - public function test_allows_disposable_sqlite_database_in_system_temp_directory(): void + public function test_creates_isolated_named_memory_sqlite_database(): void { $database = TestDatabaseGuard::claim(':temporary:', 'sqlite', 'testing'); $this->assertIsString($database); - $this->assertStringStartsWith(realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR, $database); - $this->assertFileExists($database); + $this->assertMatchesRegularExpression( + '/^file:dynamic-pterodactyl-test-[a-f0-9]{32}\?mode=memory&cache=shared$/', + $database, + ); + + $writer = new \PDO('sqlite:'.$database); + $writer->exec('CREATE TABLE claim_probe (value TEXT NOT NULL)'); + $writer->exec("INSERT INTO claim_probe (value) VALUES ('owned')"); + unset($writer); + + $reader = new \PDO('sqlite:'.$database); + $this->assertSame('owned', $reader->query('SELECT value FROM claim_probe')->fetchColumn()); + } + + public function test_rejects_caller_supplied_named_memory_database(): void + { + $this->assertNull(TestDatabaseGuard::claim( + 'file:shared-production?mode=memory&cache=shared', + 'sqlite', + 'testing', + )); } public function test_rejects_disposable_name_outside_system_temp_directory(): void From d97a0ac30932b6cb4767309e679cd78187160cc6 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 21:16:22 +1000 Subject: [PATCH 16/95] fix: use one validated availability snapshot --- 02-SERVICES.md | 56 ++++++++++++------- 03-API.md | 11 ++-- .../Api/AvailabilityController.php | 2 +- Services/NodeSelectionService.php | 8 ++- Services/ResourceCalculationService.php | 8 ++- tests/Feature/AvailabilityApiTest.php | 22 +++++--- tests/Unit/NodeSelectionServiceTest.php | 19 +++++++ tests/Unit/ResourceCalculationServiceTest.php | 42 +++++++++++++- 8 files changed, 130 insertions(+), 38 deletions(-) diff --git a/02-SERVICES.md b/02-SERVICES.md index f6fb180..e11d9bd 100644 --- a/02-SERVICES.md +++ b/02-SERVICES.md @@ -110,7 +110,9 @@ class ResourceCalculationService // Formula: total * (1 + overallocate_percentage / 100) $effectiveMemory = $node['memory'] * (1 + ($node['memory_overallocate'] ?? 0) / 100); $effectiveDisk = $node['disk'] * (1 + ($node['disk_overallocate'] ?? 0) / 100); - $effectiveCpu = ($node['cpu_threads'] ?? 4) * 100; // No overallocation for CPU + // cpu_threads must come from an explicit panel customization or a local + // capacity policy. Stock Pterodactyl does not expose node CPU capacity. + $effectiveCpu = $node['cpu_threads'] * 100; // Calculate available (total - allocated - pending) $available = [ @@ -224,29 +226,43 @@ class ResourceCalculationService private function fetchNodesInLocation(int $locationId): array { - $response = Http::withHeaders([ - 'Authorization' => 'Bearer ' . $this->apiKey, - 'Accept' => 'application/json', - 'Content-Type' => 'application/json', - ])->get("{$this->apiUrl}/api/application/locations/{$locationId}", [ + $response = $this->pterodactylGet( + "/api/application/locations/{$locationId}", + [ 'include' => 'nodes,servers', - ]); - - if (!$response->successful()) { - throw new \RuntimeException('Failed to fetch location: ' . $response->body()); + ] + ); + + $nodesData = $this->requireRelationshipData($response, 'nodes'); + $serversData = $this->requireRelationshipData($response, 'servers'); + + $nodesById = []; + foreach ($nodesData as $node) { + $attributes = $this->requireNodeAttributes($node); + if ($attributes['location_id'] !== $locationId) { + throw new \RuntimeException('Pterodactyl API returned a node for an unexpected location.'); + } + $nodesById[$attributes['id']] = $attributes; } - $attributes = $response->json('attributes', []); - $serversByNode = collect(data_get($attributes, 'relationships.servers.data', [])) - ->map(fn($server) => $server['attributes']) - ->groupBy('node'); + $serversByNode = []; + foreach ($serversData as $server) { + $attributes = $this->requireServerAttributes($server); + if (! array_key_exists($attributes['node'], $nodesById)) { + throw new \RuntimeException('Pterodactyl API returned a server for an unknown included node.'); + } + $serversByNode[$attributes['node']][] = $attributes; + } - return collect(data_get($attributes, 'relationships.nodes.data', [])) - ->map(fn($node) => [ - 'node' => $node['attributes'], - 'servers' => $serversByNode->get($node['attributes']['id'], collect())->values()->all(), - ]) - ->all(); + $nodes = []; + foreach ($nodesById as $nodeId => $attributes) { + $nodes[] = [ + 'node' => $attributes, + 'servers' => $serversByNode[$nodeId] ?? [], + ]; + } + + return $nodes; } private function getPendingReservations(int $nodeId): array diff --git a/03-API.md b/03-API.md index 3ab3985..74ae356 100644 --- a/03-API.md +++ b/03-API.md @@ -367,8 +367,8 @@ class AvailabilityController public function getByLocation(int $locationId): JsonResponse { try { - $maxAvailable = $this->nodeService->getMaxAvailable($locationId); $locationData = $this->resourceService->getLocationAvailability($locationId); + $maxAvailable = $this->nodeService->getMaxAvailable($locationId, $locationData); $resourceCapacity = [ 'memory' => $maxAvailable['memory'] > 0, 'cpu' => $maxAvailable['cpu'] > 0, @@ -387,11 +387,12 @@ class AvailabilityController 'resource_capacity' => $resourceCapacity, ], ]); - } catch (\Exception $e) { + } catch (\Throwable $e) { + report($e); + return response()->json([ 'success' => false, 'message' => 'Failed to fetch availability', - 'error' => $e->getMessage(), ], 500); } } @@ -405,7 +406,9 @@ class AvailabilityController 'success' => true, 'data' => $locationData, ]); - } catch (\Exception $e) { + } catch (\Throwable $e) { + report($e); + return response()->json([ 'success' => false, 'message' => 'Failed to fetch node details', diff --git a/Http/Controllers/Api/AvailabilityController.php b/Http/Controllers/Api/AvailabilityController.php index 5965526..1c53217 100644 --- a/Http/Controllers/Api/AvailabilityController.php +++ b/Http/Controllers/Api/AvailabilityController.php @@ -22,8 +22,8 @@ public function __construct( public function getByLocation(int $locationId): JsonResponse { try { - $maxAvailable = $this->nodeService->getMaxAvailable($locationId); $locationData = $this->resourceService->getLocationAvailability($locationId); + $maxAvailable = $this->nodeService->getMaxAvailable($locationId, $locationData); $resourceCapacity = [ 'memory' => $maxAvailable['memory'] > 0, 'cpu' => $maxAvailable['cpu'] > 0, diff --git a/Services/NodeSelectionService.php b/Services/NodeSelectionService.php index 570ecd1..f5810f8 100644 --- a/Services/NodeSelectionService.php +++ b/Services/NodeSelectionService.php @@ -78,9 +78,13 @@ public function selectBestNode(int $locationId, array $requirements): ?array /** * Get maximum allocatable resources across a location */ - public function getMaxAvailable(int $locationId): array + public function getMaxAvailable(int $locationId, ?array $locationData = null): array { - $locationData = $this->resourceService->getLocationAvailability($locationId); + $locationData ??= $this->resourceService->getLocationAvailability($locationId); + if (($locationData['location_id'] ?? null) !== $locationId + || ! is_array($locationData['max_available'] ?? null)) { + throw new \RuntimeException('Invalid location availability snapshot.'); + } return $locationData['max_available']; } diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index 3ed524b..53268e4 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -237,6 +237,9 @@ private function fetchNodesInLocation(int $locationId): array $nodesById = []; foreach ($nodesData as $node) { $attributes = $this->requireNodeAttributes($node); + if ($attributes['location_id'] !== $locationId) { + throw new \RuntimeException('Pterodactyl API returned a node for an unexpected location.'); + } $nodesById[$attributes['id']] = $attributes; } @@ -404,8 +407,11 @@ private function pterodactylGetPaginatedData(string $path, array $query = []): a $currentPage = (int) ($pagination['current_page'] ?? $page); $totalPages = (int) ($pagination['total_pages'] ?? $currentPage); + if ($currentPage !== $page || $totalPages < 1 || $totalPages < $currentPage) { + throw new \RuntimeException('Pterodactyl API returned invalid pagination metadata.'); + } - if ($currentPage >= $totalPages || $totalPages === 0) { + if ($currentPage === $totalPages) { break; } diff --git a/tests/Feature/AvailabilityApiTest.php b/tests/Feature/AvailabilityApiTest.php index 54504a2..e503e86 100644 --- a/tests/Feature/AvailabilityApiTest.php +++ b/tests/Feature/AvailabilityApiTest.php @@ -83,13 +83,16 @@ public function test_customer_failure_response_does_not_expose_internal_exceptio /** @var User $user */ $user = User::factory()->create(); - $nodeService = Mockery::mock(NodeSelectionService::class); - $nodeService->shouldReceive('getMaxAvailable') + $resourceService = Mockery::mock(ResourceCalculationService::class); + $resourceService->shouldReceive('getLocationAvailability') ->once() ->with(1) ->andThrow(new \RuntimeException('panel-internal-host:8080 failed')); + $this->app->instance(ResourceCalculationService::class, $resourceService); + + $nodeService = Mockery::mock(NodeSelectionService::class); + $nodeService->shouldNotReceive('getMaxAvailable'); $this->app->instance(NodeSelectionService::class, $nodeService); - $this->app->instance(ResourceCalculationService::class, Mockery::mock(ResourceCalculationService::class)); $response = $this->actingAs($user)->getJson('/api/dynamic-pterodactyl/availability/1'); @@ -102,10 +105,16 @@ public function test_customer_failure_response_does_not_expose_internal_exceptio private function bindAvailabilityServices(array $maxAvailable): void { + $locationData = [ + 'location_id' => 1, + 'nodes' => [['node_id' => 1, 'name' => 'Node 1']], + 'max_available' => $maxAvailable, + ]; + $nodeService = Mockery::mock(NodeSelectionService::class); $nodeService->shouldReceive('getMaxAvailable') ->once() - ->with(1) + ->with(1, $locationData) ->andReturn($maxAvailable); $this->app->instance(NodeSelectionService::class, $nodeService); @@ -113,10 +122,7 @@ private function bindAvailabilityServices(array $maxAvailable): void $resourceService->shouldReceive('getLocationAvailability') ->once() ->with(1) - ->andReturn([ - 'location_id' => 1, - 'nodes' => [['node_id' => 1, 'name' => 'Node 1']], - ]); + ->andReturn($locationData); $this->app->instance(ResourceCalculationService::class, $resourceService); } } diff --git a/tests/Unit/NodeSelectionServiceTest.php b/tests/Unit/NodeSelectionServiceTest.php index 8c16ad3..b576e5a 100644 --- a/tests/Unit/NodeSelectionServiceTest.php +++ b/tests/Unit/NodeSelectionServiceTest.php @@ -324,6 +324,7 @@ public function test_get_max_available_returns_location_max(): void $this->mockResourceService->shouldReceive('getLocationAvailability') ->with(1) ->andReturn([ + 'location_id' => 1, 'nodes' => [], 'max_available' => $expected, ]); @@ -333,6 +334,24 @@ public function test_get_max_available_returns_location_max(): void $this->assertEquals($expected, $result); } + public function test_get_max_available_reuses_preloaded_location_snapshot(): void + { + $expected = [ + 'memory' => 16384, + 'cpu' => 800, + 'disk' => 102400, + ]; + $this->mockResourceService->shouldNotReceive('getLocationAvailability'); + + $result = $this->service->getMaxAvailable(1, [ + 'location_id' => 1, + 'nodes' => [], + 'max_available' => $expected, + ]); + + $this->assertSame($expected, $result); + } + /** * Test empty nodes array returns null. */ diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index 20c4f70..36693df 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -331,6 +331,23 @@ public function test_location_availability_rejects_server_for_unknown_node(): vo $this->service->getLocationAvailability(1); } + public function test_location_availability_rejects_node_from_another_location(): void + { + Http::fake($this->availabilityHttpFake( + nodeId: 5, + locationId: 1, + totalMemory: 8192, + totalDisk: 51200, + totalCpuThreads: 4, + includedNodeLocationId: 2, + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('unexpected location'); + + $this->service->getLocationAvailability(1); + } + public function test_location_availability_rejects_node_without_cpu_threads(): void { Http::fake([ @@ -491,6 +508,26 @@ public function test_snapshot_handles_paginated_location_response(): void $this->assertLessThanOrEqual(4, $calls); } + public function test_get_locations_rejects_non_advancing_pagination_metadata(): void + { + Http::fake([ + 'panel.example.com/*' => Http::response([ + 'data' => [], + 'meta' => [ + 'pagination' => [ + 'current_page' => 0, + 'total_pages' => 1, + ], + ], + ], 200), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('invalid pagination metadata'); + + $this->service->getLocations(); + } + public function test_snapshot_handles_pterodactyl_5xx_gracefully(): void { $calls = 0; @@ -570,9 +607,10 @@ private function availabilityHttpFake( int $totalCpuThreads, array $servers = [], array $additionalNodeIds = [], + ?int $includedNodeLocationId = null, ): callable { - return function ($request) use ($nodeId, $locationId, $totalMemory, $totalDisk, $totalCpuThreads, $servers, $additionalNodeIds) { + return function ($request) use ($nodeId, $locationId, $totalMemory, $totalDisk, $totalCpuThreads, $servers, $additionalNodeIds, $includedNodeLocationId) { $url = $request->url(); $query = []; parse_str(parse_url($url, PHP_URL_QUERY) ?? '', $query); @@ -591,7 +629,7 @@ private function availabilityHttpFake( 'object' => 'node', 'attributes' => [ 'id' => $includedNodeId, - 'location_id' => $locationId, + 'location_id' => $includedNodeLocationId ?? $locationId, 'name' => 'Node '.$includedNodeId, 'fqdn' => 'node-'.$includedNodeId.'.example.com', 'memory' => $totalMemory, From a7f77f5e1ad4017748f74f4d013dc6eb33fe0e00 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 21:18:51 +1000 Subject: [PATCH 17/95] docs: document single snapshot and cpu policy gate --- .../en/content/API Reference/API Reference.md | 3 ++- .../Availability Endpoints.md | 24 +++++++++---------- .../Public API Endpoints.md | 6 ++--- .../Resource Calculation Service.md | 10 ++++---- .../Service Layer Design.md | 8 +++---- .qoder/repowiki/en/content/Deployment.md | 2 +- .qoder/repowiki/en/content/Testing.md | 6 ++--- .qoder/repowiki/en/content/Troubleshooting.md | 10 ++++---- .../repowiki/en/meta/repowiki-metadata.json | 2 +- PROGRESS.md | 4 ++-- 10 files changed, 37 insertions(+), 38 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index aed692e..47f13f5 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -88,11 +88,12 @@ participant ResCalc as "ResourceCalculationService" participant Ptero as "Pterodactyl API" Client->>Routes : GET /api/dynamic-pterodactyl/availability/{locationId} Routes->>AvailCtrl : getByLocation(locationId) -AvailCtrl->>NodeSel : getMaxAvailable(locationId) AvailCtrl->>ResCalc : getLocationAvailability(locationId) ResCalc->>Ptero : fetch nodes/servers (real-time) Ptero-->>ResCalc : node/server data ResCalc-->>AvailCtrl : aggregated availability +AvailCtrl->>NodeSel : getMaxAvailable(locationId, locationData) +NodeSel-->>AvailCtrl : max_available from same snapshot AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,node_count,has_capacity,resource_capacity}} ``` diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md index be4f35e..a3573bb 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md @@ -41,8 +41,8 @@ graph TB Client["Customer Client"] --> Routes["API Routes
/api/dynamic-pterodactyl"] Routes --> MW["Middleware: web, auth, throttle:30,1"] MW --> Ctrl["AvailabilityController::getByLocation"] -Ctrl --> NodeSel["NodeSelectionService::getMaxAvailable"] Ctrl --> ResCalc["ResourceCalculationService::getLocationAvailability"] +Ctrl --> NodeSel["NodeSelectionService::getMaxAvailable with preloaded snapshot"] ResCalc --> Ptero["Pterodactyl API"] Ctrl --> Security["Security Layer
Data Sanitization"] Security --> Response["Secure JSON Response
No Node Details"] @@ -51,7 +51,7 @@ Security --> Response["Secure JSON Response
No Node Details"] **Diagram sources** - [routes/api.php:17-22](file://routes/api.php#L17-L22) - [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [NodeSelectionService.php:78-86](file://Services/NodeSelectionService.php#L78-L86) +- [NodeSelectionService.php:78-90](file://Services/NodeSelectionService.php#L78-L90) - [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) **Section sources** @@ -74,14 +74,14 @@ Key responsibilities: **Section sources** - [routes/api.php:17-22](file://routes/api.php#L17-L22) - [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [NodeSelectionService.php:78-86](file://Services/NodeSelectionService.php#L78-L86) +- [NodeSelectionService.php:78-90](file://Services/NodeSelectionService.php#L78-L90) - [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) ## Architecture Overview The GET /api/dynamic-pterodactyl/availability/{locationId} flow: 1. Request enters the route group with web + auth + throttle middleware. -2. AvailabilityController::getByLocation resolves max available resources via NodeSelectionService. -3. It also fetches location availability via ResourceCalculationService to compute node_count and resource_capacity booleans. +2. AvailabilityController::getByLocation fetches one location snapshot via ResourceCalculationService. +3. It passes that same snapshot to NodeSelectionService to read max_available, then computes node_count and resource_capacity booleans without another panel request. 4. A compact JSON response is returned with only aggregate fields; no node identifiers or internal details are exposed. 5. **Enhanced**: Comprehensive test coverage ensures security boundaries are maintained. @@ -97,14 +97,12 @@ participant P as "Pterodactyl API" C->>R : GET /api/dynamic-pterodactyl/availability/{locationId} R->>M : Apply web, auth, throttle : 30,1 M-->>A : Proceed if authenticated and within limit -A->>N : getMaxAvailable(locationId) -N->>S : getLocationAvailability(locationId) +A->>S : getLocationAvailability(locationId) S->>P : Batched calls to list nodes/servers P-->>S : Node and server data -S-->>N : Aggregated availability -N-->>A : Max available {memory, cpu, disk} -A->>S : getLocationAvailability(locationId) -S-->>A : Location data including nodes[] +S-->>A : Aggregated location data including nodes[] +A->>N : getMaxAvailable(locationId, locationData) +N-->>A : Max available from the same snapshot A->>A : Security sanitization
Remove node details A-->>C : {success, data : {location_id, max_memory, max_cpu, max_disk, node_count, has_capacity, resource_capacity}} ``` @@ -112,7 +110,7 @@ A-->>C : {success, data : {location_id, max_memory, max_cpu, max_disk, node_coun **Diagram sources** - [routes/api.php:17-22](file://routes/api.php#L17-L22) - [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [NodeSelectionService.php:78-86](file://Services/NodeSelectionService.php#L78-L86) +- [NodeSelectionService.php:78-90](file://Services/NodeSelectionService.php#L78-L90) - [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) ## Detailed Component Analysis @@ -221,7 +219,7 @@ ForEachNode --> |No| ReturnData["Return {location_id, nodes[], max_available, to - [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) **Section sources** -- [NodeSelectionService.php:78-86](file://Services/NodeSelectionService.php#L78-L86) +- [NodeSelectionService.php:78-90](file://Services/NodeSelectionService.php#L78-L90) - [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) - [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md index b242479..26ae260 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md @@ -98,10 +98,10 @@ participant N as "NodeSelectionService" participant S as "ResourceCalculationService" C->>R : GET /api/dynamic-pterodactyl/availability/{locationId} R->>A : getByLocation(locationId) -A->>N : getMaxAvailable(locationId) -N-->>A : {memory, cpu, disk} A->>S : getLocationAvailability(locationId) -S-->>A : {nodes, ...} +S-->>A : {nodes, max_available, ...} +A->>N : getMaxAvailable(locationId, locationData) +N-->>A : {memory, cpu, disk} from same snapshot A-->>C : {success, data : {max_memory, max_cpu, max_disk, has_capacity, ...}} ``` diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md index 6e286a2..9a647e3 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md @@ -85,12 +85,12 @@ participant S as "ResourceCalculationService" participant P as "Pterodactyl API" participant D as "Local DB" C->>A : GET /availability/{locationId} -A->>N : getMaxAvailable(locationId) -N->>S : getLocationAvailability(locationId) +A->>S : getLocationAvailability(locationId) S->>P : GET /locations/{id}?include=nodes,servers S->>D : SUM pending reservations (node_id, pending, not expired) -S-->>N : Node availability arrays -N-->>A : Max available per resource +S-->>A : Node availability arrays +A->>N : getMaxAvailable(locationId, locationData) +N-->>A : Max available per resource from same snapshot A-->>C : {has_capacity, max_memory/cpu/disk, node_count} ``` @@ -144,7 +144,7 @@ LoopNodes --> |No| ReturnLoc["Return location data"] ### AvailabilityController Exposes customer-facing availability endpoints: -- getByLocation(locationId): Combines NodeSelectionService.getMaxAvailable with ResourceCalculationService.getLocationAvailability to return has_capacity and per-resource booleans indicating whether memory, CPU, and disk have positive headroom. +- getByLocation(locationId): Fetches location availability once, then passes that snapshot to NodeSelectionService.getMaxAvailable to return has_capacity and per-resource booleans from one consistent panel read. - getNodes(locationId): Returns location-level availability data for admin purposes. Error handling: diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md index dc68163..6559184 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md @@ -93,12 +93,12 @@ participant N as "NodeSelectionService" participant R as "ResourceCalculationService" participant P as "Pterodactyl API" C->>A : GET /availability/{locationId} -A->>N : getMaxAvailable(locationId) -N->>R : getLocationAvailability(locationId) +A->>R : getLocationAvailability(locationId) R->>P : GET /locations/{id}?include=nodes,servers P-->>R : JSON payload -R-->>N : location availability -N-->>A : max_available +R-->>A : location availability +A->>N : getMaxAvailable(locationId, locationData) +N-->>A : max_available from same snapshot A-->>C : {max_memory,max_cpu,max_disk,...} ``` diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index 1e73cb7..559fff1 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -144,7 +144,7 @@ Operational requirements: - Scheduler must be running to execute cleanup and alert checks. - Database must support transactions and pessimistic locking. - Network access to the Pterodactyl Panel API must be allowed from the Paymenter host. -- Node payloads must provide a numeric `cpu_threads` capacity value; missing or malformed node/server capacity fields fail closed instead of advertising unverified capacity. +- Node payloads must provide a numeric `cpu_threads` capacity value; missing or malformed node/server capacity fields fail closed instead of advertising unverified capacity. Stock Pterodactyl does not expose this node field. Keep deployment paused until PR #22's explicit local `NodeCapacityPolicy` is rebased onto this reconciliation (or an equivalent trusted capacity source is installed). **Section sources** - [DynamicPterodactyl.php:48-75](file://DynamicPterodactyl.php#L48-L75) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 769a3f4..c41848d 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -100,7 +100,7 @@ Key components under test: ## Architecture Overview The testing architecture isolates external dependencies and enforces deterministic environments: - phpunit.xml forces array cache/session/queue and sync queue. -- tests/bootstrap.php requires `APP_ENV=testing` and accepts only `paymenter_test`, `:memory:`, or the `:temporary:` sentinel. The sentinel generates and atomically claims an unpredictable private SQLite path before Paymenter boots; caller-supplied SQLite paths are rejected. +- tests/bootstrap.php requires `APP_ENV=testing` and accepts only `paymenter_test`, `:memory:`, or the `:temporary:` sentinel. The sentinel generates an unpredictable process-private named in-memory SQLite database and retains an anchor connection before Paymenter boots; caller-supplied SQLite paths and URI names are rejected. - Feature tests load routes and use DatabaseTransactions to keep state isolated per test. - Unit tests mock or fake HTTP and DB interactions to avoid real calls. @@ -354,7 +354,7 @@ The test suite provides robust coverage across service logic, API endpoints, and ## Appendices ### How to Run the Test Suite -- Set `DB_DATABASE` to `paymenter_test`, `:memory:`, or `:temporary:`. The standalone `:temporary:` database is generated, migrated on first application boot, and cleaned up at process shutdown. +- Set `DB_DATABASE` to `paymenter_test`, `:memory:`, or `:temporary:`. The standalone `:temporary:` database is generated in memory, shared with Laravel through its private URI, migrated on first application boot, and discarded at process shutdown. - Use the outer Paymenter vendor PHPUnit binary as configured by the project. - Run unit tests: vendor/bin/phpunit --testsuite=Unit - Run feature tests: vendor/bin/phpunit --testsuite=Feature @@ -398,7 +398,7 @@ The test suite provides robust coverage across service logic, API endpoints, and ### Test Database Setup and Fixtures - Database isolation: - phpunit.xml sets DB_CONNECTION and DB_DATABASE for tests. - - tests/bootstrap.php enforces the test database guard and atomically owns any standalone SQLite path before use. + - tests/bootstrap.php enforces the test database guard and retains the anchor connection for the process-private standalone SQLite database. - Fixtures: - Create minimal required records (products, config options, carts, cart items) within tests. - Use factories where available; otherwise insert raw rows via DB facade. diff --git a/.qoder/repowiki/en/content/Troubleshooting.md b/.qoder/repowiki/en/content/Troubleshooting.md index c566124..f6867ed 100644 --- a/.qoder/repowiki/en/content/Troubleshooting.md +++ b/.qoder/repowiki/en/content/Troubleshooting.md @@ -96,12 +96,12 @@ participant S as "ResourceCalculationService" participant P as "Pterodactyl API" C->>R : GET /api/dynamic-pterodactyl/availability/{locationId} R->>A : getByLocation(locationId) -A->>N : getMaxAvailable(locationId) -N->>S : getLocationAvailability(locationId) -S->>P : GET /api/application/nodes (with filters) +A->>S : getLocationAvailability(locationId) +S->>P : GET /api/application/locations/{id}?include=nodes,servers P-->>S : nodes + servers -S-->>N : locationData -N-->>A : max_available +S-->>A : locationData +A->>N : getMaxAvailable(locationId, locationData) +N-->>A : max_available from same snapshot A-->>C : {success,data} ``` diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index ea8bb38..8ee065f 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-86","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"227-257","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"452-498","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"a979596d6efe10d64710b17a20f51f7568585f40","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-90","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"227-265","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"444-513","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"d97a0ac30932b6cb4767309e679cd78187160cc6","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file diff --git a/PROGRESS.md b/PROGRESS.md index 91edf33..8edaca6 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -71,8 +71,8 @@ All dp-NN backlog items are implemented. The active reconciliation is staged on **Working on**: Draft PR #23 reconciliation and Wiki verification **Status**: Panel changes are preserved on the reconciliation branch; Qoder Wiki pages are migrated to GitHub Wiki and refreshed for the final batched location API flow. **Current file**: PROGRESS.md -**Next action**: Complete exact-SHA review, then merge draft PR #23 when approved. Resume Mutagen only as a separately authorized deployment step. -**Blockers**: PR #22 overlaps this reconciliation and must be rebased after PR #23; merging it unchanged would restore superseded test-guard and error-response behavior. No CI checks are configured on PR #23. +**Next action**: Complete exact-SHA review, then rebase PR #22's explicit `NodeCapacityPolicy` onto this reconciliation before any production merge or deployment. Resume Mutagen only as a separately authorized deployment step. +**Blockers**: Stock Pterodactyl does not expose node CPU capacity, so PR #23 must not deploy alone. PR #22 overlaps this reconciliation and must be rebased while preserving the hardened test guard, sanitized errors, and Wiki changes. No CI checks are configured on PR #23. ### This Session's Changes: From 975105c33e75d9a20ed621b0f24ec7b26887bcf8 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 21:41:29 +1000 Subject: [PATCH 18/95] fix: reject truncated capacity snapshots --- 02-SERVICES.md | 106 +++++------------- Services/NodeSelectionService.php | 7 ++ Services/ResourceCalculationService.php | 72 ++++++++---- tests/Unit/NodeSelectionServiceTest.php | 13 +++ tests/Unit/ResourceCalculationServiceTest.php | 83 +++++++++++++- tests/Unit/TestDatabaseGuardTest.php | 9 +- 6 files changed, 188 insertions(+), 102 deletions(-) diff --git a/02-SERVICES.md b/02-SERVICES.md index e11d9bd..81fa11e 100644 --- a/02-SERVICES.md +++ b/02-SERVICES.md @@ -44,7 +44,7 @@ class ResourceCalculationService /** * Get available resources for a location (real-time from Pterodactyl API) */ - public function getLocationAvailability(int $locationId): array + public function getLocationAvailability(int $locationId, ?string $excludeReservationToken = null): array { $nodes = $this->fetchNodesInLocation($locationId); @@ -57,7 +57,7 @@ class ResourceCalculationService ]; foreach ($nodes as $nodeWithServers) { - $nodeAvailability = $this->calculateNodeAvailability($nodeWithServers); + $nodeAvailability = $this->calculateNodeAvailability($nodeWithServers, $excludeReservationToken); $locationData['nodes'][] = $nodeAvailability; // Track maximum available across all nodes @@ -90,60 +90,17 @@ class ResourceCalculationService /** * Calculate available resources for a specific node */ - public function calculateNodeAvailability(array $nodeWithServers): array + private function calculateNodeAvailability(array $nodeWithServers, ?string $excludeReservationToken = null): array { $node = $nodeWithServers['node']; $servers = $nodeWithServers['servers']; - - // Sum allocated resources from all servers - $allocated = ['memory' => 0, 'cpu' => 0, 'disk' => 0]; - foreach ($servers as $server) { - $allocated['memory'] += $server['limits']['memory'] ?? 0; - $allocated['cpu'] += $server['limits']['cpu'] ?? 0; - $allocated['disk'] += $server['limits']['disk'] ?? 0; - } - - // Get pending reservations for this node - $pendingReservations = $this->getPendingReservations($node['id']); - - // Calculate effective totals with overallocation - // Formula: total * (1 + overallocate_percentage / 100) - $effectiveMemory = $node['memory'] * (1 + ($node['memory_overallocate'] ?? 0) / 100); - $effectiveDisk = $node['disk'] * (1 + ($node['disk_overallocate'] ?? 0) / 100); - // cpu_threads must come from an explicit panel customization or a local - // capacity policy. Stock Pterodactyl does not expose node CPU capacity. - $effectiveCpu = $node['cpu_threads'] * 100; - - // Calculate available (total - allocated - pending) - $available = [ - 'memory' => max(0, (int)$effectiveMemory - $allocated['memory'] - $pendingReservations['memory']), - 'cpu' => max(0, (int)$effectiveCpu - $allocated['cpu'] - $pendingReservations['cpu']), - 'disk' => max(0, (int)$effectiveDisk - $allocated['disk'] - $pendingReservations['disk']), - ]; - - return [ - 'node_id' => $node['id'], - 'name' => $node['name'], - 'fqdn' => $node['fqdn'], - 'maintenance_mode' => $node['maintenance_mode'] ?? false, - 'total' => [ - 'memory' => (int)$effectiveMemory, - 'cpu' => (int)$effectiveCpu, - 'disk' => (int)$effectiveDisk, - ], - 'allocated' => $allocated, - 'reserved' => $pendingReservations, - 'available' => $available, - 'server_count' => count($servers), - 'utilization' => [ - 'memory' => $effectiveMemory > 0 - ? round(($allocated['memory'] + $pendingReservations['memory']) / $effectiveMemory * 100, 1) - : 100, - 'disk' => $effectiveDisk > 0 - ? round(($allocated['disk'] + $pendingReservations['disk']) / $effectiveDisk * 100, 1) - : 100, - ], - ]; + $pendingReservations = $this->getPendingReservations($node['id'], $excludeReservationToken); + + // buildNodeAvailabilityFromServers validates complete node/server + // resource shapes before calculating totals. Stock Pterodactyl has no + // node CPU-capacity field, so cpu_threads remains a fail-closed gate + // until the explicit local NodeCapacityPolicy is rebased from PR #22. + return $this->buildNodeAvailabilityFromServers($node, $servers, $pendingReservations); } /** @@ -183,14 +140,14 @@ class ResourceCalculationService /** * Verify resources are still available (called at payment time) */ - public function verifyAvailability(int $nodeId, array $requirements): bool + public function verifyAvailability(int $nodeId, array $requirements, ?string $excludeReservationToken = null): bool { $nodes = $this->fetchNodesInLocation($this->getNodeLocation($nodeId)); - $node = collect($nodes)->firstWhere('id', $nodeId); + $nodeWithServers = collect($nodes)->first(fn ($node) => ($node['node']['id'] ?? null) === $nodeId); - if (!$node) return false; + if (!$nodeWithServers) return false; - $availability = $this->calculateNodeAvailability($node); + $availability = $this->calculateNodeAvailability($nodeWithServers, $excludeReservationToken); return $availability['available']['memory'] >= $requirements['memory'] && $availability['available']['cpu'] >= $requirements['cpu'] @@ -202,24 +159,7 @@ class ResourceCalculationService */ public function getLocations(): array { - $response = Http::withHeaders([ - 'Authorization' => 'Bearer ' . $this->apiKey, - 'Accept' => 'application/json', - ])->get("{$this->apiUrl}/api/application/locations", [ - 'per_page' => 100, - ]); - - if (!$response->successful()) { - throw new \RuntimeException('Failed to fetch locations from Pterodactyl'); - } - - return collect($response->json('data', [])) - ->map(fn($loc) => [ - 'id' => $loc['attributes']['id'], - 'short' => $loc['attributes']['short'], - 'long' => $loc['attributes']['long'], - ]) - ->toArray(); + return $this->fetchAllLocations(); } // --- Private Methods --- @@ -379,9 +319,21 @@ class NodeSelectionService /** * Get maximum allocatable resources across a location */ - public function getMaxAvailable(int $locationId): array + public function getMaxAvailable(int $locationId, ?array $locationData = null): array { - $locationData = $this->resourceService->getLocationAvailability($locationId); + $locationData ??= $this->resourceService->getLocationAvailability($locationId); + if (($locationData['location_id'] ?? null) !== $locationId + || !is_array($locationData['max_available'] ?? null)) { + throw new \RuntimeException('Invalid location availability snapshot.'); + } + + foreach (['memory', 'cpu', 'disk'] as $resource) { + if (!is_int($locationData['max_available'][$resource] ?? null) + || $locationData['max_available'][$resource] < 0) { + throw new \RuntimeException('Invalid location availability snapshot.'); + } + } + return $locationData['max_available']; } } diff --git a/Services/NodeSelectionService.php b/Services/NodeSelectionService.php index f5810f8..09050e5 100644 --- a/Services/NodeSelectionService.php +++ b/Services/NodeSelectionService.php @@ -86,6 +86,13 @@ public function getMaxAvailable(int $locationId, ?array $locationData = null): a throw new \RuntimeException('Invalid location availability snapshot.'); } + foreach (['memory', 'cpu', 'disk'] as $resource) { + if (! is_int($locationData['max_available'][$resource] ?? null) + || $locationData['max_available'][$resource] < 0) { + throw new \RuntimeException('Invalid location availability snapshot.'); + } + } + return $locationData['max_available']; } } diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index 53268e4..32d8be7 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -82,8 +82,10 @@ public function buildClusterSnapshot(): array } $snapshot['locations'] = $locations; + $knownLocationIds = []; foreach ($locations as $location) { + $knownLocationIds[$location['id']] = true; $snapshot['by_location'][$location['id']] = [ 'nodes' => [], 'totals' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], @@ -97,6 +99,9 @@ public function buildClusterSnapshot(): array foreach ($nodes as $nodeId => $nodeData) { $node = $nodeData['node']; $locationId = $nodeData['location_id']; + if (! array_key_exists($locationId, $knownLocationIds)) { + throw new \RuntimeException('Pterodactyl API returned a node for an unknown location.'); + } $availability = $this->buildNodeAvailabilityFromServers( $node, $nodeData['servers'], @@ -116,15 +121,6 @@ public function buildClusterSnapshot(): array 'node_availability' => $availability, ]; - if (! array_key_exists($locationId, $snapshot['by_location'])) { - $snapshot['by_location'][$locationId] = [ - 'nodes' => [], - 'totals' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], - 'allocated' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], - 'available' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], - ]; - } - $snapshot['by_location'][$locationId]['nodes'][] = $nodeId; $snapshot['by_location'][$locationId]['totals']['memory'] += $availability['total']['memory']; $snapshot['by_location'][$locationId]['totals']['cpu'] += $availability['total']['cpu']; @@ -313,13 +309,17 @@ private function buildNodeAvailabilityFromServers(array $node, array $servers, a private function fetchAllLocations(): array { - return \collect($this->pterodactylGetPaginatedData('/api/application/locations', ['per_page' => 100])) - ->map(fn ($location) => [ - 'id' => $location['attributes']['id'], - 'short' => $location['attributes']['short'], - 'long' => $location['attributes']['long'], - ]) - ->toArray(); + $locations = []; + foreach ($this->pterodactylGetPaginatedData('/api/application/locations', ['per_page' => 100]) as $location) { + $attributes = $this->requireLocationAttributes($location); + $locations[] = [ + 'id' => $attributes['id'], + 'short' => $attributes['short'], + 'long' => $attributes['long'], + ]; + } + + return $locations; } private function fetchClusterNodes(): array @@ -392,6 +392,7 @@ private function pterodactylGetPaginatedData(string $path, array $query = []): a { $page = 1; $data = []; + $expectedTotalPages = null; while (true) { $payload = $this->pterodactylGet($path, array_merge($query, ['page' => $page])); @@ -402,15 +403,29 @@ private function pterodactylGetPaginatedData(string $path, array $query = []): a $pagination = $payload['meta']['pagination'] ?? null; if (! is_array($pagination)) { - break; + throw new \RuntimeException('Pterodactyl API returned invalid pagination metadata.'); } - $currentPage = (int) ($pagination['current_page'] ?? $page); - $totalPages = (int) ($pagination['total_pages'] ?? $currentPage); - if ($currentPage !== $page || $totalPages < 1 || $totalPages < $currentPage) { + $currentPage = filter_var( + $pagination['current_page'] ?? null, + FILTER_VALIDATE_INT, + ['options' => ['min_range' => 1]], + ); + $totalPages = filter_var( + $pagination['total_pages'] ?? null, + FILTER_VALIDATE_INT, + ['options' => ['min_range' => 1]], + ); + if ($currentPage === false || $totalPages === false + || $currentPage !== $page || $totalPages < $currentPage) { throw new \RuntimeException('Pterodactyl API returned invalid pagination metadata.'); } + $expectedTotalPages ??= $totalPages; + if ($totalPages !== $expectedTotalPages) { + throw new \RuntimeException('Pterodactyl API returned inconsistent pagination metadata.'); + } + if ($currentPage === $totalPages) { break; } @@ -421,6 +436,23 @@ private function pterodactylGetPaginatedData(string $path, array $query = []): a return $data; } + private function requireLocationAttributes(mixed $payload): array + { + $attributes = is_array($payload) && is_array($payload['attributes'] ?? null) + ? $payload['attributes'] + : null; + if ($attributes === null + || filter_var($attributes['id'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) === false + || ! is_string($attributes['short'] ?? null) || $attributes['short'] === '' + || ! is_string($attributes['long'] ?? null) || $attributes['long'] === '') { + throw new \RuntimeException('Pterodactyl API returned an invalid location payload.'); + } + + $attributes['id'] = (int) $attributes['id']; + + return $attributes; + } + private function requireRelationshipData(array $payload, string $relationship): array { $attributes = is_array($payload['attributes'] ?? null) ? $payload['attributes'] : []; diff --git a/tests/Unit/NodeSelectionServiceTest.php b/tests/Unit/NodeSelectionServiceTest.php index b576e5a..4b9c94a 100644 --- a/tests/Unit/NodeSelectionServiceTest.php +++ b/tests/Unit/NodeSelectionServiceTest.php @@ -352,6 +352,19 @@ public function test_get_max_available_reuses_preloaded_location_snapshot(): voi $this->assertSame($expected, $result); } + public function test_get_max_available_rejects_incomplete_preloaded_snapshot(): void + { + $this->mockResourceService->shouldNotReceive('getLocationAvailability'); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Invalid location availability snapshot'); + + $this->service->getMaxAvailable(1, [ + 'location_id' => 1, + 'max_available' => ['memory' => 1024, 'cpu' => -1], + ]); + } + /** * Test empty nodes array returns null. */ diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index 36693df..f16a461 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -39,6 +39,7 @@ public function test_get_locations_returns_parsed_array(): void 'data' => [ ['attributes' => ['id' => 1, 'short' => 'us', 'long' => 'US East']], ], + 'meta' => ['pagination' => ['current_page' => 1, 'total_pages' => 1]], ], 200), ]); @@ -389,11 +390,15 @@ public function test_snapshot_falls_back_when_included_servers_relationship_is_m if (str_contains($url, '/api/application/locations')) { return Http::response([ 'data' => [['attributes' => ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']]], + 'meta' => ['pagination' => ['current_page' => 1, 'total_pages' => 1]], ], 200); } if (str_contains($url, '/api/application/nodes')) { - return Http::response(['data' => [$node]], 200); + return Http::response([ + 'data' => [$node], + 'meta' => ['pagination' => ['current_page' => 1, 'total_pages' => 1]], + ], 200); } if (str_contains($url, '/api/application/servers')) { @@ -404,6 +409,7 @@ public function test_snapshot_falls_back_when_included_servers_relationship_is_m 'limits' => ['memory' => 1024, 'cpu' => 50, 'disk' => 5120], ], ]], + 'meta' => ['pagination' => ['current_page' => 1, 'total_pages' => 1]], ], 200); } @@ -528,6 +534,80 @@ public function test_get_locations_rejects_non_advancing_pagination_metadata(): $this->service->getLocations(); } + public function test_get_locations_rejects_missing_pagination_metadata(): void + { + Http::fake([ + 'panel.example.com/*' => Http::response(['data' => []], 200), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('invalid pagination metadata'); + + $this->service->getLocations(); + } + + public function test_get_locations_rejects_inconsistent_total_pages(): void + { + Http::fake(function ($request) { + $query = []; + parse_str(parse_url($request->url(), PHP_URL_QUERY) ?? '', $query); + $page = (int) ($query['page'] ?? 1); + + return Http::response([ + 'data' => [[ + 'attributes' => [ + 'id' => $page, + 'short' => 'dc'.$page, + 'long' => 'Data Center '.$page, + ], + ]], + 'meta' => [ + 'pagination' => [ + 'current_page' => $page, + 'total_pages' => $page === 1 ? 3 : 2, + ], + ], + ], 200); + }); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('inconsistent pagination metadata'); + + $this->service->getLocations(); + } + + public function test_get_locations_rejects_malformed_location_payload(): void + { + Http::fake([ + 'panel.example.com/*' => Http::response([ + 'data' => [['attributes' => ['id' => 1, 'short' => 'dc1']]], + 'meta' => ['pagination' => ['current_page' => 1, 'total_pages' => 1]], + ], 200), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('invalid location payload'); + + $this->service->getLocations(); + } + + public function test_snapshot_rejects_node_for_unknown_location(): void + { + $calls = 0; + Http::fake($this->clusterSnapshotHttpFake( + $calls, + locations: [['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], + nodePages: [[ + $this->nodeWithServersPayload(1, 2, 'Orphan Node', []), + ]], + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('unknown location'); + + $this->service->buildClusterSnapshot(); + } + public function test_snapshot_handles_pterodactyl_5xx_gracefully(): void { $calls = 0; @@ -540,6 +620,7 @@ public function test_snapshot_handles_pterodactyl_5xx_gracefully(): void 'data' => [ ['attributes' => ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], ], + 'meta' => ['pagination' => ['current_page' => 1, 'total_pages' => 1]], ], 200); } diff --git a/tests/Unit/TestDatabaseGuardTest.php b/tests/Unit/TestDatabaseGuardTest.php index f94ecb2..95d6b9e 100644 --- a/tests/Unit/TestDatabaseGuardTest.php +++ b/tests/Unit/TestDatabaseGuardTest.php @@ -25,12 +25,13 @@ public function test_rejects_existing_arbitrary_sqlite_database(): void public function test_creates_isolated_named_memory_sqlite_database(): void { $database = TestDatabaseGuard::claim(':temporary:', 'sqlite', 'testing'); + $secondDatabase = TestDatabaseGuard::claim(':temporary:', 'sqlite', 'testing'); $this->assertIsString($database); - $this->assertMatchesRegularExpression( - '/^file:dynamic-pterodactyl-test-[a-f0-9]{32}\?mode=memory&cache=shared$/', - $database, - ); + $this->assertIsString($secondDatabase); + $this->assertNotSame($database, $secondDatabase); + $this->assertStringStartsWith('file:dynamic-pterodactyl-test-', $database); + $this->assertStringEndsWith('?mode=memory&cache=shared', $database); $writer = new \PDO('sqlite:'.$database); $writer->exec('CREATE TABLE claim_probe (value TEXT NOT NULL)'); From d65c73d954159e5f4b2298af78e2cc075ea8d4e4 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 21:44:17 +1000 Subject: [PATCH 19/95] docs: align strict snapshot contracts --- .../Public API Endpoints/Availability Endpoints.md | 10 +++++----- .../en/content/Core Services/NodeSelectionService.md | 10 +++++----- .qoder/repowiki/en/meta/repowiki-metadata.json | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md index a3573bb..c0ce99d 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md @@ -51,7 +51,7 @@ Security --> Response["Secure JSON Response
No Node Details"] **Diagram sources** - [routes/api.php:17-22](file://routes/api.php#L17-L22) - [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [NodeSelectionService.php:78-90](file://Services/NodeSelectionService.php#L78-L90) +- [NodeSelectionService.php:78-97](file://Services/NodeSelectionService.php#L78-L97) - [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) **Section sources** @@ -74,7 +74,7 @@ Key responsibilities: **Section sources** - [routes/api.php:17-22](file://routes/api.php#L17-L22) - [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [NodeSelectionService.php:78-90](file://Services/NodeSelectionService.php#L78-L90) +- [NodeSelectionService.php:78-97](file://Services/NodeSelectionService.php#L78-L97) - [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) ## Architecture Overview @@ -98,7 +98,7 @@ C->>R : GET /api/dynamic-pterodactyl/availability/{locationId} R->>M : Apply web, auth, throttle : 30,1 M-->>A : Proceed if authenticated and within limit A->>S : getLocationAvailability(locationId) -S->>P : Batched calls to list nodes/servers +S->>P : GET /locations/{id}?include=nodes,servers P-->>S : Node and server data S-->>A : Aggregated location data including nodes[] A->>N : getMaxAvailable(locationId, locationData) @@ -110,7 +110,7 @@ A-->>C : {success, data : {location_id, max_memory, max_cpu, max_disk, node_coun **Diagram sources** - [routes/api.php:17-22](file://routes/api.php#L17-L22) - [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [NodeSelectionService.php:78-90](file://Services/NodeSelectionService.php#L78-L90) +- [NodeSelectionService.php:78-97](file://Services/NodeSelectionService.php#L78-L97) - [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) ## Detailed Component Analysis @@ -219,7 +219,7 @@ ForEachNode --> |No| ReturnData["Return {location_id, nodes[], max_available, to - [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) **Section sources** -- [NodeSelectionService.php:78-90](file://Services/NodeSelectionService.php#L78-L90) +- [NodeSelectionService.php:78-97](file://Services/NodeSelectionService.php#L78-L97) - [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) - [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) diff --git a/.qoder/repowiki/en/content/Core Services/NodeSelectionService.md b/.qoder/repowiki/en/content/Core Services/NodeSelectionService.md index 3152dfc..5db14a4 100644 --- a/.qoder/repowiki/en/content/Core Services/NodeSelectionService.md +++ b/.qoder/repowiki/en/content/Core Services/NodeSelectionService.md @@ -63,7 +63,7 @@ RCS --> PTERO - NodeSelectionService: Implements best-fit selection using weighted headroom scoring and filters out unsuitable nodes. - ResourceCalculationService: Provides real-time per-location and per-node availability by querying Pterodactyl and aggregating server allocations and pending reservations. - ReservationService: Orchestrates reservation creation and calls NodeSelectionService to pick a node; enforces pessimistic locking and idempotency. -- AvailabilityController: Exposes safe customer-facing endpoints that return aggregate capacity and node counts without exposing raw node identifiers or FQDNs. +- AvailabilityController: Exposes aggregate-only customer availability plus a separately authorized admin endpoint for raw node details. Key responsibilities: - NodeSelectionService: Evaluate candidates, compute scores, and return the best node or null if none qualify. @@ -207,12 +207,12 @@ Flow highlights: - [ReservationService.php:43-124](file://Services/ReservationService.php#L43-L124) ### Integration with AvailabilityController -AvailabilityController provides safe, customer-facing endpoints: +AvailabilityController provides separate customer and administrator surfaces: - getByLocation(locationId): returns max allocatable resources and whether the location has capacity across memory, CPU, and disk. It does not expose node names or FQDNs. -- getNodes(locationId): returns availability data for the location; while it includes node arrays internally, the controller’s contract ensures only aggregate metrics are surfaced to clients. +- getNodes(locationId): is admin-only (web + auth + EnsureUserIsAdmin + throttle) and returns raw per-node availability for internal monitoring. Usage of NodeSelectionService: -- getMaxAvailable(locationId) is used to determine per-location maximums for capacity checks. +- getMaxAvailable(locationId, locationData) reads per-location maximums from the already fetched snapshot, avoiding a second panel request. **Section sources** - [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) @@ -297,4 +297,4 @@ Operational tips: ## Conclusion NodeSelectionService provides a robust, weighted best-fit algorithm that balances memory, disk, and CPU headroom to select optimal nodes for resource allocation. It integrates tightly with ResourceCalculationService for real-time availability and works within ReservationService’s transactional and idempotent reservation workflow. The design ensures safety through maintenance mode filtering, hard constraint enforcement, and clear error signaling when resources are insufficient. Customer-facing APIs remain safe by exposing only aggregate capacity metrics. -[No sources needed since this section summarizes without analyzing specific files] \ No newline at end of file +[No sources needed since this section summarizes without analyzing specific files] diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 8ee065f..0a06004 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-90","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"227-265","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"444-513","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"d97a0ac30932b6cb4767309e679cd78187160cc6","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-261","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"439-545","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"975105c33e75d9a20ed621b0f24ec7b26887bcf8","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file From a349b2a16820229804f5cce2c44134cc50d82ad7 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 22:03:11 +1000 Subject: [PATCH 20/95] fix: reject duplicate capacity records --- Services/ResourceCalculationService.php | 28 ++++++++- tests/Unit/ResourceCalculationServiceTest.php | 63 ++++++++++++++++++- 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index 32d8be7..5496d10 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -236,16 +236,19 @@ private function fetchNodesInLocation(int $locationId): array if ($attributes['location_id'] !== $locationId) { throw new \RuntimeException('Pterodactyl API returned a node for an unexpected location.'); } + $this->rememberUniqueId($nodesById, $attributes['id'], 'included node'); $nodesById[$attributes['id']] = $attributes; } $serversByNode = []; + $serverIds = []; foreach ($serversData as $server) { $attributes = $this->requireServerAttributes($server); $nodeId = $attributes['node']; if (! array_key_exists($nodeId, $nodesById)) { throw new \RuntimeException('Pterodactyl API returned a server for an unknown included node.'); } + $this->rememberUniqueId($serverIds, $attributes['id'], 'included server'); $serversByNode[$nodeId][] = $attributes; } @@ -310,8 +313,10 @@ private function buildNodeAvailabilityFromServers(array $node, array $servers, a private function fetchAllLocations(): array { $locations = []; + $locationIds = []; foreach ($this->pterodactylGetPaginatedData('/api/application/locations', ['per_page' => 100]) as $location) { $attributes = $this->requireLocationAttributes($location); + $this->rememberUniqueId($locationIds, $attributes['id'], 'location'); $locations[] = [ 'id' => $attributes['id'], 'short' => $attributes['short'], @@ -331,6 +336,10 @@ private function fetchClusterNodes(): array throw $exception; } + if ($exception->getMessage() !== 'Pterodactyl API returned an invalid servers relationship payload.') { + throw $exception; + } + return $this->fetchClusterNodesFromServerIndex(); } } @@ -338,17 +347,20 @@ private function fetchClusterNodes(): array private function fetchClusterNodesWithIncludedServers(): array { $nodes = []; + $serverIds = []; foreach ($this->pterodactylGetPaginatedData('/api/application/nodes', [ 'include' => 'servers', 'per_page' => 100, ]) as $node) { $attributes = $this->requireNodeAttributes($node); + $this->rememberUniqueId($nodes, $attributes['id'], 'node'); $servers = []; foreach ($this->requireRelationshipData($node, 'servers') as $server) { $serverAttributes = $this->requireServerAttributes($server); if ($serverAttributes['node'] !== $attributes['id']) { throw new \RuntimeException('Pterodactyl API returned a server for an unexpected node.'); } + $this->rememberUniqueId($serverIds, $serverAttributes['id'], 'server'); $servers[] = $serverAttributes; } @@ -367,6 +379,7 @@ private function fetchClusterNodesFromServerIndex(): array $nodes = []; foreach ($this->pterodactylGetPaginatedData('/api/application/nodes', ['per_page' => 100]) as $node) { $attributes = $this->requireNodeAttributes($node); + $this->rememberUniqueId($nodes, $attributes['id'], 'node'); $nodes[$attributes['id']] = [ 'node' => $attributes, 'location_id' => $attributes['location_id'], @@ -374,6 +387,7 @@ private function fetchClusterNodesFromServerIndex(): array ]; } + $serverIds = []; foreach ($this->pterodactylGetPaginatedData('/api/application/servers', ['per_page' => 100]) as $server) { $attributes = $this->requireServerAttributes($server); $nodeId = $attributes['node']; @@ -382,6 +396,7 @@ private function fetchClusterNodesFromServerIndex(): array throw new \RuntimeException('Pterodactyl API returned a server for an unknown node.'); } + $this->rememberUniqueId($serverIds, $attributes['id'], 'server'); $nodes[$nodeId]['servers'][] = $attributes; } @@ -499,6 +514,7 @@ private function requireServerAttributes(mixed $payload): array } $this->validateServerAttributes($attributes); + $attributes['id'] = (int) $attributes['id']; $attributes['node'] = (int) $attributes['node']; return $attributes; @@ -532,7 +548,8 @@ private function validateNodeAttributes(array $attributes): void private function validateServerAttributes(array $attributes): void { - if (filter_var($attributes['node'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) === false + if (filter_var($attributes['id'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) === false + || filter_var($attributes['node'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) === false || ! is_array($attributes['limits'] ?? null)) { throw new \RuntimeException('Pterodactyl API returned an invalid included server payload.'); } @@ -544,6 +561,15 @@ private function validateServerAttributes(array $attributes): void } } + private function rememberUniqueId(array &$seen, int $id, string $resource): void + { + if (array_key_exists($id, $seen)) { + throw new \RuntimeException("Pterodactyl API returned a duplicate {$resource}."); + } + + $seen[$id] = true; + } + private function emptyClusterSnapshot(): array { return [ diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index f16a461..49e13c5 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -332,6 +332,26 @@ public function test_location_availability_rejects_server_for_unknown_node(): vo $this->service->getLocationAvailability(1); } + public function test_location_availability_rejects_duplicate_server_records(): void + { + Http::fake($this->availabilityHttpFake( + nodeId: 5, + locationId: 1, + totalMemory: 8192, + totalDisk: 51200, + totalCpuThreads: 4, + servers: [ + ['id' => 501, 'node' => 5, 'memory' => 1024, 'cpu' => 50, 'disk' => 5120], + ['id' => 501, 'node' => 5, 'memory' => 1024, 'cpu' => 50, 'disk' => 5120], + ], + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('duplicate included server'); + + $this->service->getLocationAvailability(1); + } + public function test_location_availability_rejects_node_from_another_location(): void { Http::fake($this->availabilityHttpFake( @@ -405,6 +425,7 @@ public function test_snapshot_falls_back_when_included_servers_relationship_is_m return Http::response([ 'data' => [[ 'attributes' => [ + 'id' => 101, 'node' => 1, 'limits' => ['memory' => 1024, 'cpu' => 50, 'disk' => 5120], ], @@ -608,6 +629,44 @@ public function test_snapshot_rejects_node_for_unknown_location(): void $this->service->buildClusterSnapshot(); } + public function test_snapshot_rejects_duplicate_node_records(): void + { + $calls = 0; + Http::fake($this->clusterSnapshotHttpFake( + $calls, + locations: [['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], + nodePages: [[ + $this->nodeWithServersPayload(1, 1, 'Node 1', []), + $this->nodeWithServersPayload(1, 1, 'Node 1 Duplicate', []), + ]], + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('duplicate node'); + + $this->service->buildClusterSnapshot(); + } + + public function test_snapshot_rejects_duplicate_server_records(): void + { + $calls = 0; + Http::fake($this->clusterSnapshotHttpFake( + $calls, + locations: [['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], + nodePages: [[ + $this->nodeWithServersPayload(1, 1, 'Node 1', [ + ['id' => 101, 'memory' => 1024, 'cpu' => 50, 'disk' => 5120], + ['id' => 101, 'memory' => 1024, 'cpu' => 50, 'disk' => 5120], + ]), + ]], + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('duplicate server'); + + $this->service->buildClusterSnapshot(); + } + public function test_snapshot_handles_pterodactyl_5xx_gracefully(): void { $calls = 0; @@ -731,7 +790,7 @@ private function availabilityHttpFake( 'data' => array_map(fn (array $server, int $index) => [ 'object' => 'server', 'attributes' => [ - 'id' => ($server['node'] * 100) + $index, + 'id' => $server['id'] ?? (($server['node'] * 100) + $index), 'node' => $server['node'], 'limits' => array_intersect_key($server, [ 'memory' => true, @@ -824,7 +883,7 @@ private function nodeWithServersPayload(int $nodeId, int $locationId, string $na 'servers' => [ 'data' => array_map(fn (array $server, int $index) => [ 'attributes' => [ - 'id' => ($nodeId * 100) + $index, + 'id' => $server['id'] ?? (($nodeId * 100) + $index), 'node' => $nodeId, 'limits' => $server, ], From b078be96c81eabc6551682e27028d0a18d346063 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 22:04:08 +1000 Subject: [PATCH 21/95] docs: record strict identity validation --- .../Resource Calculation Service.md | 6 ++++-- .../Core Services/ResourceCalculationService.md | 13 ++++++++----- .qoder/repowiki/en/content/Testing.md | 1 + .qoder/repowiki/en/meta/repowiki-metadata.json | 2 +- 02-SERVICES.md | 4 +++- PROGRESS.md | 2 +- 6 files changed, 18 insertions(+), 10 deletions(-) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md index 9a647e3..605b270 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md @@ -116,6 +116,7 @@ Data flow highlights: Error handling and resilience: - pterodactylGet() sets per-attempt timeout and connect timeout, retries only on connection errors, sanitizes exceptions, and throws meaningful runtime exceptions for rate limits and non-JSON responses. +- Node, server, and location identities must be unique within a snapshot; duplicates and inconsistent relationships fail closed before resource totals are calculated. - buildClusterSnapshot() catches failures and returns a degraded snapshot with an error flag when Pterodactyl is down or returns 5xx errors. Examples of usage patterns: @@ -232,6 +233,7 @@ Common issues and strategies: - Rate limiting: A 429 response triggers a specific runtime exception instructing callers to retry after a delay. Tests assert that 429 does not trigger retries. - Server errors: 5xx responses are treated as Pterodactyl being unavailable; buildClusterSnapshot() returns a degraded snapshot so consumers can degrade gracefully. - Invalid payloads: Non-JSON responses raise a runtime exception indicating invalid payload; tests validate this behavior. +- Duplicate identities: Repeated node, server, or location records are rejected rather than overwritten or double-counted. - Missing node location: getNodeLocation() validates presence of location_id and throws if absent; tests assert the expected exception pattern. Operational tips: @@ -240,8 +242,8 @@ Operational tips: **Section sources** - [ResourceCalculationService.php:157-195](file://Services/ResourceCalculationService.php#L157-L195) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ResourceCalculationService.php:410-424](file://Services/ResourceCalculationService.php#L410-L424) +- [ResourceCalculationService.php:454-571](file://Services/ResourceCalculationService.php#L454-L571) +- [ResourceCalculationService.php:421-438](file://Services/ResourceCalculationService.php#L421-L438) - [ResourceCalculationServiceTest.php:53-139](file://tests/Unit/ResourceCalculationServiceTest.php#L53-L139) ## Conclusion diff --git a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md index 1774501..3750657 100644 --- a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md +++ b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md @@ -109,9 +109,9 @@ RCS-->>Caller : Cluster snapshot or degraded snapshot **Diagram sources** - [ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) -- [ResourceCalculationService.php:291-384](file://Services/ResourceCalculationService.php#L291-L384) -- [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:313-404](file://Services/ResourceCalculationService.php#L313-L404) +- [ResourceCalculationService.php:405-453](file://Services/ResourceCalculationService.php#L405-L453) +- [ResourceCalculationService.php:454-571](file://Services/ResourceCalculationService.php#L454-L571) ## Detailed Component Analysis @@ -134,6 +134,7 @@ Return value: Processing logic: - Fetches the location with included nodes and servers in one Pterodactyl request - Groups included servers by node and fetches pending reservations for each node +- Rejects duplicate node, server, or location identities instead of overwriting or double-counting upstream records - Computes effective totals using overallocation settings - Subtracts allocated and reserved resources to derive available - Aggregates max and totals across nodes @@ -147,7 +148,7 @@ Usage pattern example: **Section sources** - [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) - [ResourceCalculationService.php:146-152](file://Services/ResourceCalculationService.php#L146-L152) -- [ResourceCalculationService.php:226-245](file://Services/ResourceCalculationService.php#L226-L245) +- [ResourceCalculationService.php:223-264](file://Services/ResourceCalculationService.php#L223-L264) - [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) - [ResourceCalculationService.php:500-522](file://Services/ResourceCalculationService.php#L500-L522) @@ -233,7 +234,7 @@ Integration with reservation system: **Section sources** - [ResourceCalculationService.php:359-391](file://Services/ResourceCalculationService.php#L359-L391) - [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:454-571](file://Services/ResourceCalculationService.php#L454-L571) - [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) ### Class diagram @@ -334,6 +335,8 @@ Common issues and how they surface: - Throws a RuntimeException with a rate limit message; callers should back off and retry later. - Invalid JSON payload: - Throws a RuntimeException indicating invalid JSON; indicates upstream misconfiguration or proxy issue. +- Duplicate or inconsistent identities: + - Throws a RuntimeException before availability is calculated so repeated upstream records cannot distort totals. - Missing location_id: - getNodeLocation() throws when the node response lacks location_id; indicates malformed upstream data. diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index c41848d..b25b085 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -180,6 +180,7 @@ Focus areas: - Real-time availability fetching from Pterodactyl with pagination and relationship extraction. - Error handling for rate limits (429), server errors (5xx), malformed JSON, and connection exceptions with retries. - Cluster snapshot aggregation across locations and nodes, including utilization metrics. +- Fail-closed rejection of duplicate node/server identities and inconsistent upstream relationships. - Self-exclusion of current reservation token when verifying availability. ```mermaid diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 0a06004..4044402 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-261","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"439-545","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBVcsEy5TNHlP/Xz/D/ELaiZcLqVqvsFHZojMIvWXbqtAYqvdZNM8XlBghzpiqWnEov1SV7FQtFPIpj9j/EofU1iDJXVRmqaz5fZFYghM4g6eO9cJ4FK7JsL738Jk9Pp80MZLg8hV/wWALidFrhbh/4LOB+9n+7zkzR2sBNubQpQ8CJCXywcf+P2+Pve3bo4Q2XdnYCEud4sF87/Fh6XF/yl4YV+aVoUDW7tlISB4ZX7+yVhkBU+MHlkjh9Q3wsb82HFvz1GL4gR/pxDMVhhLV6eIIEJvhbXFJ9TfG5Rzkaobf7DkZX6CNWPqRb1vIa1SqQnWSD/KPpeGKRH+B/DFqBZ7eb/hSKBeb14MrTIKWuu4wRF7kOKMIJBVuMYWQrX6NG5oUKP1xUvJjDeerXVq7kG1AlJV1VqD5Da0c4KGBNIMelVdcLVBQOj8hqIM/vlr7KRkfTC1wKtE2Qz5glBCmIymh76+xzX8DCyNNMiLn+wCCGDuPzz3Fzqv8twRVUsvSfg/QLe0aWjgM4Rw+BePhdj3uGonWLcJ5ZvyKyAVlrM7gUoUMBz/KJiAlD4FAsmXPvIbxnPN0ApMDTVbThe14MgVc03fnMupeiO+tlEUSIpFtR5gIoV8ys/O3FZhtCRzI2DUqbXiqgrxSQ57B0nFSTKfuxl/yiBFRzI3+V03TtTUZ7P5Eg+v6wipDcAka3ri8fJWQU2mYgQkevu3K89lDHiaoMoTry8Vyn/wGR5dNvPy4s7hCsI5irNVhNWfZ9r6CqdoAxe2J4b2TbkeUQy7yb2RSbL5neccpDzlTBYIaTUZHvFwYl8dcbit+0GTXs7hFz4wiHKAWbNnjtTbGLFKLDzfBfrjA7TpLB03o+elWdqBN7rPnNy10tZf4EPIa6do65PecZ2hTDlydEJbb4nDOaklaESrjqhGkf165rK7eIbSKEyYHHbPycQhlkSvUdC3MamKUVQutZG46YTPy1ncD3CXhlIbO/VC2L/IZNrJD5WsqK0SaZII5Npo1R2/GM7P9k2hX00M+bo31khxj7QI/QC5uibD2Jx6ziB2BRGTNOYPQudB1IAZk4uvsQ+giuDZ/o4FZvQNqislT7Z4Ow2ji9qRk+lDNq65aguCByiNEEpUpA45EA8ZZypAR2Hkt+UaOq1FhzTcKEFSUbz/oyp8G7IUi1+5cMFfYyYtReYki+9ACci5DyyMrZKqznID2Gyl353hmIAIhcc17jW/QmIIHxFJ10eqs4yjyuISQCDq8b0Vho0FfatTBaV4nsWlecER3pH31ovCsTEBsIGFhDE4s2YD3WIstIMlL80k62Lz77x5HB3xkAkb05Nvq7E0NY+EiJ0KUJqUAST0bIQWxdLUL+Rg9NgCGbUPsl9J3khXYJ+5BcAHRQ2Qn5MJog60AwSaxXT5JM+b7EFXUbPLJBqbsPktU+UevN9OnstD1z6xZ6X4cWXQrV6D4TWM0sUtU8y8QaivnVp4s4iYwLfrA+cEHtwgJ+5PrHPD5FSjswMY2Z7bu7Tgu5Txo1oKSABpv9in19t+HrwN96Ik1yNFe85QpLLF4F+Y5zQZU9ZDYtCg6illkCxGGOBCF0v5SMF69/tkU5KUaEVk90va5y5tKsysiU92Ds3eJkOLf39k8sUJtH0yFu18Jbaw2GDFpO/d/VkB797dJLrLKZOeYFeATUISpwfU06aFMubaqXyblgKy3+S9ki/fVVX5z6ThiXVs35OPUAKrq6ChluTdaPEbFFo0zbPYDpxEsd40/pybI/tgV7fFfXHwW4LUfcIZzS7HZkTqfcpBBLT/5t+cZ+LwSbtzrwc12elLAT4nvgcay1JkLDXREXYcalhltzpxhCrpaPu8qks7zzyy7bTfKGzzzEqAIh9wfb+3ONdQe8aCOFyB6uWxX8OLuuGWsa/vajo4XG7EeUA+z7dLlfPJFmsxkhpMHYScbbjT/SSkhlwZlXowmqqN/3AtHQ+m8TLOJKbdXj3Z+wHVKQQtV3hKuD/X8OW/D4TdgpS0/n9o8Nj8BP3b0qkM","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted:6mjqr/IowaZHmZRFDheV40UGsQ0sVJEEfQuKG2umzvjguvQXGNDi1nl747nCkFgOsOds5jYVCKsejZB5Ycp55oXbpBTWUOFuTcbJi+3ZrQm9i4kbql3UWJNNseqDdzVBXYHp7WTzFhQ0U5rqZB4uDZ61rmVX/LpmmgFuevs1x8owCRFo3w/YQxC110zOuoxFXRy2D7RBc6ZTQZk/Reik/DkkqHuXW1aYatf+BkXbpHcpfYrOqk8p9/VEp0mMj0gECCQO0Pqw4Hd/Sv3nADV41c6kckej0v9kJtXhZqOzBdsFT7mLWuylMl+qvHsaHJ0MDt5MzrpvlfrgBeGBF5Midf8ReNZ6ORrydHNfFH09xJE6cpbKTERWFXgTyuay7GSWk5DakToppKb1wHNu0axV5Iq6vDU/uFLj1Nshh92Rdd/Nu1PY5z+2DpuP/55wMgC5+trljToArBiPQOHJAn4PtzRb7TLb+cSeKIxDddZ0ZmkGII9iJGE5gsK+DqnvDEAnbNBlGwbz5SIC+7PUjI6rja91bfQSJVQleSXZt86XHg5MtKJ9EwDGiHfHOD5jfZKwxPWwV/qECGdRIM78OQo5SUuP6twlgFU/UnnGz7dRSHYYeoR5mdmHDNZS+3bThmZbxUgjSht5CiCg+6eaiMcph3vjsDgefJtfFegbIm50KOBcyFp/oS2o3GYLVYHq4Hs2iT2VB/R0b6N36KLn2i6o3cfqgzKAI6QQ1C7jRX+8iREvlX3lBr//FC1VuUjr4iORHHlHGiAYFO50FtKAbrzk9gdnSj/zENTdsp6cR32Pbikqe7VjE7lio3O6NQcNHlypZIcUM+6Kyk+NUxn+LDngSqWYvrLat+AA5GqBFxhmhMrSFE0N3KLrPKC+NdWo99CaBzTZ2A+bbwas+ZajkwtAP4yAR+r8xFyf8kqQJ2tzMX3Hu3fs/ZY5IL1SLOpUeolvQV1APALj4BbcSDmNdJ9+mzDyRnbHeUgoxP7vYaqUQhqO7QQK3q26sySlLGLC/HkuR8NMYBsWaAxDopofmdR1ATxpAKWQyqQW0bGBQOPISzTIroTNSM4RPKIH/wyC2e/stnHcI2UnMoRO741LRUdkDYjkoZ4pX71D5l0fIekJjyJVA9Y7yTKy0s6zBxOnGFh/5As6sWSqEt/KBUXi+w2JtZAsIgHRsuH9UkmJD4i/83YgEIkuaxKNDyiSJc18vS9qZfLAR3k6dIDnCeqx2EUM57Hw2X3lHksgjYxhueVcr9sltsnMjqSvWjTJcGusE+pg+8z8MDo4GUxQt9ZGaUS4ZvT+aMTcjHJXKoT7xs0XgHJMGzLEiKvjeO3Xw0Iys459ym3Ju0jEogWDGsNP+5GSkpYhtX7kVR+zPlQuTlNYPIW9kewpAq+PoPYmy4i2WKlJ01CF7HVyHK73SJ3cASCVTlxVlPoO8faKhwLDgEEmWBNQKMfE4WudF8NSSYf3+qVwzpVlXjK5Ws64YYGZb87dbP7Vc4Mr9KSdsFKOouyOkHfWjwGNOSjiMC/pL5mjRILIh7Lo+fccxeFT4m1nTHIQ5YGG8M5Zs3NJr2dlmf8BEc0G4q9qr9M+lzefp+gykp4fS4zsnw/DGl38T/eqr9Tq+saf9MLlHZE/KI/+soLxPv1McH9P3SeGZCVlvxlGSFoO1Beqn1guVZWP0T5Vvs0GDZhcb7HqkmxidrJAMfVnTde6+UT5awe/iqtB8M95DigmGKah/I9I4gqTYGRnHLI4C9AQR3yxlke54c1/hifk7Xj5XKrUXEKBxfyF3P3TY7GUMmtndNA9a06sonBYWM2kytc0U4e0AvSuPhJeEWoR7QGZqo0c9bdkhlRsV65XFj640N9n12eEBa4G96+SXbKVqj+zKeECjLiyMCKx3wDLHa9Cs0VK3KIcl3heMF6lMIzAZOKESrs1ltPN6CT3AV6bSp3F2jT/46EQw9KJYDDUJKdunvmZdpah00g56m20GiY4Jg/7g6Ka46DENUcU62j4muR/DrcMxA1hEfrzTjcGp+f2pze2z9WX5Mv7gC5W90ozOfEvK1HTP6Tc0JqLRj2U2DN5Q+PRfNMoiI2JhfhQm9Chbqmoc86RL3z1A7N88M6VPqamzyPLwzMBXt40Dh9qsi1tNVwA/s9TP1Q7fT3IOCOoclDAbadPOKQMQLHAwas2/1sFNyfDGBSuahQ0LtNbs5oNRHBkhLr+2DFiaeU8SSo9hDAKRzxUiCOiHNFt2XRd4c7zs46e9mJCd+pGIIDEDKKTDfD+Mi5vpVMSivc0q3OW8GuKSYqbVKEG+Gz9HxnmcGOrDcJkRrCulqicsKScSX5/6bWoCabWYIGTsC3KZSueEu7f7xbsyeocxHcOCtU7L5evb6lwfNaaboCWcTVtQK//aet0C70B28WMA9Wly02VeyiGD/RGYWCM7Cqhw9cn63O9UPBKpaoCza2BErOXWtOd9BYJrCahN1jzCfWhDWWquHd+SixiIg/ApExEl7LhfWDhH/yc1kc8K7hq9OlD7gzfJICamZcYrkjZRBx7LebsiA/vdOcyNxDVW7TZ8H9IaAhsuynHN+8hOIBpem1R6ASKkuJLZVzPtPr6nWvHE3Xekh2VLXKhZNd2vN630Zn1KLTKx3mieZk+Ojpa0oXplkte1QA8UDEBLVAXkhbuF9011k2Bd49V0BvMoFT4TDLVJtZ5vQODFyo0C6P3yUpxBKiIYN+DjDuGENy3jZcIQYXIodgg5b0jgVGTMS5uWJSRewUjx/UgZNmbCq6LibeowRk2JiqL4DmiKay2mkQa6BlLFyhjYwWTHddGNj3NrON+35+AN4dpdCkkCr2/kMPv5mnzgi3QJIqWUJXUHdUg3ZbQmG/yf58hLn3J1bLayAu4pSI5cMd7iDOcPx5j5+QzQSAVo5X3Oa1xmq6jiDh6/AAASkH16Hv0sASVxuE8TRWQFm88YShX/aUQcTgte0tD1b0EpuAAceN496lJMmSVM5izotMtraTUMIND3ytV+Q+nXF7PiN7N5HUD6At5Xg32nwCbQ4vF3nhQjOt5820Pem4fG82RyiZw9U3SA+uxVhaXcdV+WCG6wUh/15yTOBbdvgKt9pSm5uYioEumFQOHq76xkVgDmqmFo+4u5k+LUq/PUjYSFBiJ53/t+xu7lz3ZC4pCsqVO0cFPHust3mBOod8pBAh01dCPkD3oYfwnWBPf+MbnhO79AzA6UsP9Bfi0KOv/yLrgVXRaVMZGw2C62K+4pLxQkV0oaX4D07sVGZWTtlGn/BOFvX/MyM+17PAYd4OaEvl5gk25vy5cdm0PbYUX3DZFob/92IDZe6wXDqzc0rAIXRjCOLcabHIKGvMG3BV188kWylEKAzIJpvHKecNawEBwR2xNjR+fMAZ40sNzLD0vMxQhWgC+pQT4EiC7GgCmQBssy18L3QxWYnhjfws4CmhpeLRMk3PwCLNGw+p4xpa3v+G+mLeNlv0FABA4mYmEeOYhqSCfB+jFw4Chi5+72zUGzapammzIh/0GwNYA+WaA+q4z6atxIjj1r17hOM+jO7RGdcJjHxLcFMujfG3Vw0qpmqLO7CCVTvKxkDgMo7lTLTDhRB2nn6bYw27Sg4/SMcy00PIQ9UyIGzhoJIFDTGp+GnFCVqjbknucTfn88utRVQrKT3iOdSHV6G2r0i4byvp1nOtfK06l2mzCE4kVP5Nm2KuYSotlAGrKZPezokOOmWQSJhguOKILjeAYu6lf4MttjIF5ySTVpJ5CsWXs+bZY3pKN2KS3xY2hZtXmxM41S0cfnQJXH0ydWGsbBNLIwVhaha/boR9zi1owv6qWynnFkuASutH+VJtgoqYtge42bGIm8IiVlmfB3Z2q7kNchPgFPm7kfIALte/FLswFb6GL8hLW9O4pEG10vRWPrMkxu/5Cm0dM92QSW1njxOEYj0jHEwr37ZBVJKE2P5om2/9rjYU6CZg4MTD1ybE/t7Gquwnb9x8wm3NdsR3fhVPKOlJBh/XA7PYCDy20HtVSmvStbm0pho/HUmEVfyGQIrgbMTb6IAhumAKWb7NVkMkMhQZjbmXa0Wf0cAyZCwBLBY7AnwFuQ9niRrsjpQAeqGZWtyK2OE31WezwkpoR/X7U7IvsmnR1FvIGZAkKLIph00z7YguWain7pmC675sboI6TmC6XiI8mizzm6xi4F9tXE24+8LAF5Ff7Om4mSZgtyFVbDyTUKKIqXB8UftRmbUbf7sUnl73HsMrl1R+AB9rqOKvgQax9ip3OXwVGFcoPRMwqRlFLoFJ5TkW3FqTCrdC5mVDMAAXNvxHJiBL04K+0pyV5wZ9twfdJhZVR+OfNsUckWFf8MVuWsG7gtuzYCPSbUJjWiK6e2NtzdQTrWyOgpTUkoTqmrNofApyekFDaxJn0tjYeU3sPXMbvb9w+PA7j/l8qkplDfNiEnWRjljtOktshJHGeRYRIKpKcxWV+1iguw+czhG49VFPQRgK9xrtRjCsr5n7tAGJlO1VlJCEa2gOE6IW/Bco3YysRsVBI3dedsoFSVfs9DwTcTNIW4VqaT4MN5EtmVeA65cvfoHpiNQ6ef+ax2AVulUiXFFDmP7yDVMursb0FcXm7KIeDlFC8FRpMa91fp6nc14RrzF441OIyya4T5vbotuokwULzEP695MxWEBHhR64MIZjRScsp8oQKonpHbIec9spVDYiN1HaQW23HAq9bumrRlFiHH6nEKV3H9pXLfVsCtknfLhm9c8JyP4Dx0dFCxJB7Y3v1J6I0QOtj7wb6hrYcGl1+3cBPJyon0gk51eAspwzeHLHiuiEpuQnoNL+1fL3Z40orysvlX1cvpMol9bdmlE4XgbIXVf7KSJL3zI/FkUdoQUqLmYsVs/g5ZpQwrMz3aewxCAl5uOw6sPHhs2NYlYwrdwyGE+zUkDCyf3BssHA4/crZP47IQOnRufr7ZFa90o4IyCJ5wthw+T+c+h0VGeaNnhdRNp/TyQ5HNR4/qN9EdxO7tr1aJfF56hummn7yaTxsI5mIbmJi8uOKGTJU7RHiGIsWukchtx3HEwYBDfNbetAxcQo+1CLHmqs9tp7PF24BP6Qd7BS0nrdRz3nZJlb8cdJygLpDPj/4rh7HmB0e0EOg/2RUUUnRE0ZIZHRuJD2gXv0ZFEF3qIfgXW8XFjplaEnkihIdcnbhR9dl+ZlSB+bABD8w6q20smj/bBz1r4PaMsgnA4UIzHMLWV54yX07E11atWtmN9tiTovj1xuuqAwT3tNr0ZCcJz/2mi7DLYwAem/DKExh3hab4BtDKEWfkghoJZCJPwHQkuc1m6tABgoIs3hqQNfBKJDMINEMnpnvlD/C2ol3Mawo7EbdicIiGsc+poqrky3tLrEtZoOZ/zft6lb8pQM/mNvX6ij6oYH7lYvdtSASOmlkqtuSKyWRxlAASZVociul3HU1q9Xt68iDOvls+aFS+Op14OcvKzqpOTbW/6gZizQkohhXlujGKecvQ+V+WAnLEDgk0W2cA0Mlqt9A1A0HPHt/CND4J2LJm4AulxA+sfXYEmSv861YyYq9VaD0tq6p1LVpwQ3cm5HjWcv1idt8807Z1L2Id7ER/N7uOUS7L0k2UniL7P6QC4IEJW4JVHvQJaO/7Xc7DeUIkv1SiBiGVzrardAiMAI6hSafaWZwAvwsn5GfU5Ng9Uz6JoGf+I1rHgZwb6PP9YAkFUXlFFBqX6CQQt+9axTPKKd/AZ9w6IHHIRIXwjRnLupSoiV7JvgrpQNcQoY0LHxAF3lTlBd91gKvbwWAYTiv0QdBTgJTV9Uuc4Zdp9R9vNTtfs6OpInFvQc0bmKZXoTF9P6+iUetATQfRshlgx4BjtfK9khPcDSsCG9336Lptz40AUh4nmPzxXNZKI+nTfkGoGCIfqVvoUxwlgzFVyngSIll0RlNPMaejUabKI2uvLdBDmnVZLtvK6fW1OxjXHhhSdWwFjxv+favZ2y+suXte26AmFOIuyv2Rm6L9ir76htUVDmawHsczq4PJUZG4OtD8D4JKgGzX7Vg9n8EZGBGykh29VRFkV1oHR3DYTHuldeBQ3z/lyBRB8t39OWaqRQ7IrLD/0ZyLn1bB2ZvtTo6MvW6yLb/ckvkMvQXe9noPrpbHHnEHWnrrCtbVeWWOsMVBYjUgFKLJzeRxYUk+vibIKEz3a4/fTxll10kOIsOjIp+x/dchyU+lezTz0W2esT9pfc5mnIachMdOYDqlP31+OUrIYYX89P2cd/u+mDIPf4F5hR61WWUI4dKHEp+fRgRCOrUk84LW7kezK3W0B7ri1r25kF/2k7gwkEVBL21zmLXYXNFCMCBJCMc3iVDvKYCktLPUOyCheO63oRVbGCgL4LgDKP3gObuwT9xTUDZ+L/cjdbykPSbOBQdrCTWM81gq1n13ehk/T1jPoepjUGMToGvfbBfhAtXvDpgs1ly36iHB7ZxZCG/6n5PgFzjk4szJqH7QfHijwW9sJ3t388W/npXzXYu56ESyau3yVwRhKJ7xqT/E7woImUiwkRE4kwg4tk3eQp415DIsAgkSCyNqTooX9T2udnd+708V8Nwl/B4zXLGzOJQG8QrVfiuYEqRLReD057NhtQ/D/T2U7KGLAM8cWMC0JeVQgn+/tS0CcEhxWwBmVwIp7zLbkWqezjc35Z7mcRepBKS1Db1iTdM7YQdlkj+XP8me5+SHNzzCdfhpNvKMSsvFAFiIJeUU087OD/wEnMh3V6Ki8NXl5sYeVWm4qi09QNYPFgl0z/3eU4K0k3i9lOsGUuBSm6wP+0YTT2ppve5AmA6ioi+d1dbPZLnVAISA+LT8ObdTeW6T0wYbwM4bg/qQ6dOzsKfDpLmyfcYWmNS2FArFhua1s66ZIXGObc1IcvwdHU6gPWdFnkWGSTk7DwNJUyQXooUrNkYL+x8tx14/kOznj4nFBfaT9KQiiMNZVNbSb7I7HjynQG5I1rnPr52Q+yhJOXPMoEaRwDpe4pi0zTMNNEZMmcFWLa8KQi1A4wkCerMyvQhgf1WyJqOX9O36SaJZZxEdG13f3+PvtJNFvMn6iJKnJ1JuyadrAnOVwx/KaNbyNy0DuVmzeh0maLdTIy1yY3d1a77XlcNIZDAC6dAS4V3pVYogzBBRD6FP9kyMpQK22LJcijv2JCyS92gCJbAiR2wRCOYf1jImPbeDOFLCGK2DDLihrdSWMPXzx46qJ38IF0UuGxosv0tL7iZt4TrOXZQXtckkMCNZpLYgH65d4PXF9s4NRA00KmfLdh0z9ihpggvqjkXWQCMsef5c8jBivY/+e+xx1XY+7pf5zBbqi6+MmGvkRnhbmLhOcyJ/bqnVfXcLcrmMUoZtMk6m6yD6kLYau8zhrwR3ZdIQwQ7N3WfMbIo8hd2FekMVIDz4cVfzGtEkQSPIIjmJeUMZ2TsfM9jyzXkUMPKetiALE7UtWxfQ6eEYPOWLNjzbh0sGp+EUoB+6OvP/1RZzDvAncgz/nWjIAS8H2S4LrQTO34s5LGGZmDLRl9f/fVVrwfiWBAeiD0kBXSYTNeJW4wULnzSWlvYr3ll9lCaWdQOnS14yJFEW05VafnYQ3UM+tlbJlFozQ1zehZxNc2Pv3KF4yFp0r8o0fYtMkMnvA8Xh9dmvJ8A/tt7GImE7fvCZKxANwej9Raaf0eCwLZfdW3lS7FB+CZ9y48kXntYMU9JxFUnqoVQrF+hVMBjMRR0abCVXfOVAwbxvdAxIrY8qV+jVGa90WvhAkKkgh+Hf8yCiri6+ifiMfDnv+k1W0UAwQj0dLPop8z3y09Pn8A9G80BEPFmI91s9HJBsAPXccTYveHQktvoUk7Qq+W8b0dAsjsQFs8BcTvGwvQFCYvLo22JMgHL54hZvcvvC1M6sc8uDfzPiQAj6orQhe60GhvE+35362Atxb/fCtBAaKGebYAAMRFg+wsfAH4aEzHvhSFVl42JGPakQS7s2bTx0cbVnMLsBSSji47jIXqAXtiduTFP36loKpYOl7n3KmR7bLcewC7AeNctVIIQ+0JeM+5FjJEQ1EgYA/Ax7GmC+hdXezes3eKI1c6dMOjX6/3lF00DjU4+AvhBkrR3M3ZJAWqr9pSB9fy8vmQRanQxj0Eln4SKNu8IaZ4WbqlEEmbOFJ6u4Io0RSvKzklYMzlm38bNqqEckKRNGspPs7uqYvFfqG2HmzKtzJVJuKvj5zInVSXD98FHeTFA4Eg2qwYhb2H76Pqdb9GFOMODMHna5A7uU7jrSMKTK0goNnv7UZAPSYdWdAEE0E4kHh/F1Jo3J3tOfqXI4ELr9skT6zKbOl6YDbPFDMgUF0IhgO9zQhKrNTf78qxC1KK+lA8KRdFFQb+PWgT72S+ME8dufBZYKNvbhX/QlkgrDm2qmwIU50VKz8MCXCQnYEmjp6jiyqd1FmZyyMg9N0AXgHaPAQwzWAmB/G/YJOGjmk7g1+eu/m1GCOljgkooweAOnryPDQEBmgcG9T1ps5P6ps+Ya6uiU7TdbZYgAZVI6oxeFIPYeGtMqCiMkwDcmWEfYlp16lFc4lVrhpE3wMtXl8/h3UsrNcY4jHEnsWf5L7wV3ukaj722ZjoQOkGAFIRiMyY8F0CshW44gtLgWetKFAlJ9ISdV6GOFb91ONxkUbRHNoWthbRayDDBOixZIi/5w9LMwGSfxfCyzYlnGgBvxxZS/POsYb9WjAVOgYqj1+gA65EpkINO5PzzG35AF+ti3s4QqSQWtuW6ZW3Ry6uThtt/Tw0EDlFDUIXd5K/o3/U6EYl94tslMYDc+AIoEWRTkqTsbsm6ZlJwQ7ARR6pJNWX9/7NbE9VjDXFhhVJwnKWCg9dTi5ifCRMW9eH0ek0hg8fwYi8daC3JoJHxhyo1nWT1HdxY7Q+UxdvBh84hlvXvwD/pA8mD9/NYSVJ2n1O0PVGMC6oQuA2SFQ19/+z04TkDQEi1x4uI3PvE7w3kRn3kfev7JrSJ7508vfEPT3MylzWYGnNNjlstjJpkubu5BRDzKC+nZwylJhJUhrhGCH+SfNH25r59CTULN9buN3C9ZB7Ea+gsFvnZ1TeRDY5tzP5u4RzCkrUlC9uhhd/y2BXjMzZD1xwL3FCXMECHccdnKFfpjbUrhqVFJ3RubK1osuMzNHQ6WR7Dy11GLbvEXA0F84yos72fYJQxYgjUb7w97j50wmnnL8DXDXrQzFxX8Ahwa6PtHwRH8FyCcnvqmH92eCU6JUf92bp3O8J8WKGBO+pfvcFSCpvtZhRpvbMlaus5d3Or7b5YmFqk8ROVqDqFPIEhb6dyDQsdzrs/N+X0hwLCg9cDxpb5r7JOg24OBgqtQOPsOCK6rMj/b7dmPIbmaI2su0QMeNCO0wUpim2/7GiVNgmq3I2Jlwg6ZlhZyz03TiGygZc3nLzdH75C0zPglSVXojAWCJps2cIHUozW/0ivvt22v9+WwcHMnMUfj1GGWs69rtru7urW3Xz0bcX5sAkftMgsB05YdWZJhZkMiCldJMkGfvhUo61x2DRig0p9+WhKv0TUTqABK+WAbT4yjgJUS3dTGFpOGqmWZZRVD6xXEFCsRg0mSDubYcSU2YoPE4k0676dXLj7L75BGaAskadGF7n2eAxJ286S28xa9vm4yVZDYlTZae8eI+3pFTCbFevS5J0kGdZ0TSzy1NclOpOPt7vnT3LzBEYjxjILS6xFmg5+WXnGyAW8YDip0bSslLGkRd7SaolhkcCDz6r0s7gZjFtQbqdScI4odDP1JEweS7TSw+40K71Au698JTMvI8WnIcowhu2blG2b/kOQfGGlaUUNZoVnWNw1IofA8mCYAPSNwPhMsKyBPaKPvY5KAgCAIfHBnyJyXwOXRQs9Sdld6+LtQcuIBv/zeHlF6w3xZxlGbiC6G7Hb2Wo2TJfUJ4tACJnONM8BpETTzFtptGgNipolfvjb1+vNsWAByCkv60yOBlFQcAUzVu0ZZzSGNTSYEqgd5gYtqRNOjXpAIZTxw77wIkfH319Ud1LdZmh29ynRBprzEWjUOi66Q1dRoLIDK7pVsItHaDTmvv4ZnSQNhYqyifgnpqZLRzG84/vlPwipBkOlO4L+r1zpZvvqY92xyhoPnL+ODrrFvaKqI4aHdJBIQdMGJecD9t28ZLhkGuUG2QNpIp74uD8eJUu4qAB8FapCHd+kbaQnXlH6MzzinR7wrcgWB2ONA3E8vPjzmZhiaqi7ZFfm8M8AdVWOdxZYhzBWtK+/CiL/7AO9cOQx7tzl8BNb0hK51P6PZrfnitbvLw6FIRv9x5Wdr3eITxCLOm4hjKr+yKGSG+wilmAejJw5I+eFZSNQ5vYrITiICkpFodOC8V5F5EqeosnDvQIcSs5OeR2AC8bPxWjB6xi39ET96Txz7UUC/NxihI0SZBMmVd4S0ks/kb0RDR85/T2bnlGsRfaxa1LYBKkjGMgw0SwWAuqRoJltDK5RIFKEFdlh5tSmsA1Or8T+PDd59CfOee3S7N2twMQLZnTyZMafxdcmP67y4oPZezP7Bnt+wNqF134fyckNDfmXkBRucAW/OuhZS0NkA+3nOdCBq11LlDoTWgy1OW2ljr9/HbAv4VqJJ0YmqdOjBc3mEP7kOcB56VkzZG4TbgUBxSFn4YzDMDI26MAik4zLCiJHTUKonEQ9tvp62qqO1nXIt7zV3l/4cyzyhTQlcFkXV8PjKBYH4qTUz6Nbxao3h6J+WmfKTZ+IvYGl4VxKteJJTpPSv+QWNgqqgVavZW8XsHZzukUB5IRZ7/H4Df7ABQxoj0LzBzE/75ePugTJuzKFQaVHn43L+NVo0ccFQkC9kTiNg/vzAhRVtslEXSKwneKpm1pIeZWNdZhccTrQ9gLciXENj/W2H3GfvMv1vHIoeBKqaOSOgrx9ThjiQuKex3s1U/lBBC2ke1euyeRJ8M8K30fbY9I71fAAIYV6CDK+FZIWroAss2pHFYpkIfIyZCdc0LV5X9xUrLVHCLx842ip9FbyCj+jw8zr8AqG2Ad/1H1veTeRDo81gktDHY/1cLWgncmuueupisWDTjod7wbnFF73prWdsWJbBh2FyKAsupPUIi04tiV5Xi9LZynAf6Aejt6IP1vKpqkqg0mgIXPWx11JD3Ck39iPElppAzPlUklgCH5CtoacG7KTzrVJD60VLALKPCaJGXoX0vBl4z0sNzbx3JWrW2bZPLRez4J4EK15PpJ/5TmsuTQy28NivG9ljUB2KMQXO9WcDdvZ1/VqFaBb/OwhtDdHPkQAFOYe7uW/fgTeTFgHx/NCnzEMzx7B79UHiabsHDdBAxTNLophWX+5tUfY7qxLweL9hxSq4+hVt5/QUzKmhVvz4UD2Lx1FRAJS1EOdUrSmmso6Q7jklo0e7sGZEwKSxUEF2KCXXb0r8qTjUExpQqdONtE/aU28jpqehsHk7XRhPE2dYPS03q/Gm+T85nLBc2cyQ0TYYx2Ejj4GqXeNjXkWc3mZ192ZsOxyh3ucq/9d3JvR+SzMdS4HKPyju0YbeK+mX+NFm6bnrRakiOM9nZsEUs8c2SPX+70lMzaPBEWNpfFrBVPtWxqRSSpT6Jce4C7L5jJeGfT1+lCSooYRKNgsNeifaQDgPs1vb/Mu3xRMP1ZvqSKtFRYm50eguxyYzvg/VeWunsvTn7csVEAUQEfRj1dcLokLmWk0gYX4fN6ftixM255HXKIHjfx23S+lW1gGSz7SAVuR86ew7fmwDY6u1R2vqRBEM9g2Ualy96gx6GZbgQ2v5/y6/aGLCTAWSNwZaUHNihS0KggKyqQP6fK2PZbaCiiKmzWbhsGjOVoRM9j/VFlyHdgFYoGIoRjfU19PCjZhnCmm7Lk8XhReADCMZXrUvlvNbe0JCzGPGoYTn0HFVVCoXM/7LxASiRghqIjmF4OWqLVFTQ3sc1pBbRo5BsDcJFIKf7G4laq5a8EpMO6jKX0/rXx2RJKUIaRlHGUkSPX48tuOsFNrpgwozw/TE+xSl03ZU+vLHctHLwXEcojbuB9PAt4K+CSZu/zzbYsA86LUH9p+tc4Xzgn6bX8Ztl+iT1zmrGKh/RWDjZ2tJiLPEThKC+ihW+D2AXn/I0SLTFmddJhnc+TLBlPUJl1G4q+F62bhYZH3aJJx5YiOllGpu+/C9GsjN/D+b0pT6V20p0F6sb2bwhhxl9aV+yoL+O4zJIO9FQv+HI6nz3qXdSZt/lZVltoYmw/mCKmyA0Ka140Y1WH4gTTG7nU+Q1FM/gIxRy3ncptjOYZvQfLhYoFv7Avt6o5zzxHoti9VqMt9j410SHYVKQefZMCnY57FmI0yE0bt56TwrXs2IUUFQ83P9kmjP4/AAgjeC8chzIR6x08UjsUvv1z+PMD490ZDWEI6ThAWTAlJB0xMWzL49F25B6HTtdwj3EsByLbjiZnXwhB0wnoiC408/ho1QEpk2QkrtOkiAf3kKJqgHjRtv4UQ6WwhoqkAq7xLRlTKtvtfm87JM0xQJ3XT/72BaS0fdusbwFPXolosfpeHFLqtDMsWPYb7QVDJI6+wtB7DG4FSlRfqQXCH5IkKnlZxTgap2Qd1EFG9cHkivPVMNgdhaKX5Ek30p+65qzPwrQsRtpMjk1bjqL5sH5yZMIF10GJIgajMshf5qx6SlMAdjB5o3t9HK0oZCfBk10eEXXlCXhOCyMYjtQFl/dk7OwJU1oR3olm168FhFz0DPGiyuoLYZ5ZZYVJTh8YShowibINrW+uyztaFNCnVC2orjpOMEnEUeQw0JD7LkQwG5XLYBRXZugCSZm4Qftmpq4FBPgXGjqEmriNDK3chpxHADXSdYnW5NmEp82CvWti+YU1wCyGWA2MEHu7wE7lIiF6wLKBvIs479hJrOISPOQpl0p1SoE7rIOmGmVFMhBljW/l+/d0oTWVcGYkltEPHoScYsdDBgN+sHWnjkat1Z1yNkqOA/U7J3dPfL9vM8NSbiz7vCOnRgcNtjJitxkbYZGXy4WbbCwFFP30v6+fc9tPM99l5Nz2z4EfHwcQnUv91eNXox3LsnzaW3fSED/PhetXI3hkU0kWkPezG4ZkuIdriEuhuHiKjgDTmBQWXno9TDxkQj/aUql09QJa5N1UPmce53Y5uXqanGG4SGyQ9s+epdT5Vigc6Q1lC+i6ZeBTlij3vT4575jFkIqv8d/1X/XWoBEgtqrZP6eLSaYLo+r3Wr87hzRP39q05HUQ3fkt+00HmT9QC7h2rEMxR5ZWt1pGJSgcPZqcVgvsxPUTxtxqom+uv5Z6gODyOjG5CSlQY0ALfBz6JsPhAE/q+YTsCtTSMmz6Uy0R/Coyoeht4nqagfm/FoqfC7dG9qtc+FY3LTC2r3mjNHS6ar4QIynNPF1j9S1HQAqhJDBqcXRk0iH9XTlXq/0p8AkdDhQ35Eb421xJpgcVkTgBAl8fn7ZwDhc7zy4QXVXitL2x2wDhbbEfLvUKO0DsfA3pq/uCQJc+FiUGKWuVyItZHmSFmrPXHsO2xc/X5l35qbJIM+4iyfCizhRmufFsQwoA/kIyp4+nVNmtQXZ3J1P+NAaEFf6u046uNTxVxwVFEkaAkYPhGGI0aWnxId62Z3nJFDgwg+E9AlW1iWAvJewOIPwqSrfl59ZWxProiUO0htNns68hZCiDI466Phqw3p6GsAZ+8vHk+4EIHpmXm6QiqY+OrGHFB9d0YWBEGOvWfoBi2Ly0Hy2ftH4NoxTYJJx3TgmtgvG22xBaLAzd206yBcV2rfs72Q60U4LKl2nRojE5LnUXJNNDBfGp1RjaTmtPyGwMJk4WhMZilTf8mrjktyde404TJGSP2mtMchTyMdJFfZvqpMrfnfMsuQw1sYVfJPa9aij/dGVaxMqrGJxdPVxIeuYVMofV3hweFVrAZWJVdu5SrrRRbAAgF1mnAcrZ8qjOcftMA5VuCupRV81hZLIryA9Wmw9RcXumv9NR1LqGCQjc9l/OP+a5n85XkUxGY4YqdVQE5Fn9y7KHU3o5REsgBxf9spOWTo0BiX8Z7QjDNcKlIbFbJCGVwtRLZyIUpuGknCjh/fzQqpaJQT37pCFmmAtmULb0Nnj6bnGxLjs68r1y5UWadqmIRbB5HZ7oljRYo1bXKOMKRtgwYXS9LFEppyQzwbiR974QZWRqdIEs9wfx6nQLashFS6tG14v5s3FV/fTFmnczwwOq6sJb+4ZGYDJtYVPwSWtYJvEWaG3fGUz4GdeZPajnoULvy8QQnlCCqT8Bkmxsp8zpGwzoNbBGsw7NfU+1HvOm/KVkn/rVbeejpKvx+QfqzvtUsoi3atH3eowS+DZ5GcPfQfSSgREqv4GntJt4Kp3jd3Wjn7mTBYXF2sAJKTROvumsBiEkZu2EIsA38Fc3Ui2GwELKHoSAyp+0JY7rWJB1TQ3yxcOqKlkpZNIWQBfg7mgLfrmHeJ09fQMRomFjfHTXDQ/X6C3oyUwWiPeFNh6ePrS81SP5FzlomMahrmEbirk6yIggnI8TZZsXOvMvs2IdwFV0wFr86Vw1Z7az+dg9X6SAm29aCCK/JsBTN6NF8g3FekeUGYZFIQ/0Q6BMGhCKSFFBxW3AkhZE0Rj4IarQG7Wpnss/As/IPYOq6LyZVpAAKg9R1ihA5xN9Rxv62yoh6StTU3YoG40rvyVUm1jvmR6d8maXUMN8H2RwbA2zrVVhy0ZDqxIIi7zloZVE7TmjiSht2Fz+zVb2+5uUvoB3EnmzCIAtmYPDYtWBuRL8ymFbPX0GmEjNGEnokfOdKcUiI51QTmrLUnp0rf4r91ispSQjeRi15vBCff5qf2zZNVHjfjZQBidMAauaXpijbhdnj59faJnyrfWITXhGFcQiwqYbgfc7NRAKbUYklqOtXMb2n3L/oiCgJuY94RwyWOlY4w5McWksQTppOPG2jME+/pyljRUNIWHMmOVJaf/ysT6suX1kYEZRgQp7KR0yAsE+iQFaEjYY7FlmSsYxSYlNzElzA7gs4eQ7x6tCBB2pbxss03SJl56Eq7rFOsBfGlWMsN/8afazppu5MS0oJTKvcGshtzJhfRqbfxoemD/a1KK4KE2jb0TUnA7yeVCLJcUB4DLAUC3nxhusw3K5TdBOV+Cm5s1+YTuGPncGlzjd0UREp6UNtzWBWN9DdFKHfwqUv8+TGysrlxBFYXCefqXqDfePM1/Bw4fPLeiKaHaJoQOt5LJMZxUGYuBlXAmOxGhDIBrOdN/GKOgo/kIM5Qo2HS25WmIZ3Wcn9EimR07RUXBxEs+I7J7Nw1uBvpzjGtItCNrZXCxf9Am4OEvzKYarWW4DUdLWqzUWEjfxaGdkFo0KRzYH7aHi5paFIjned2xSh7xs7AIknGVNj008ao/hdwrgEOWNXixJtjnYVYTWhxKxcdxyBzehvUtl5nohfhpBzPqRwg7DVRr+mGtj6zI8Db9F03oaGi+vBgg6UHs3SWEcCJ+impg/QGlKERraKegmgdc0oe/HEbOjvly6uMWRUoKjkbZGpnDmuuOFKwLBBSTV2GIvbgLpOP3kgbChkTRgBJXvbqo9e5rmlEfRCA/qJLjHN/qYkSdZfXPG6FL4WswFMQQJfvmrb4aweoVjdUjWDcY9oJeIJIPbRcxOMKwODZ/EmV1gCJxwvjNd9lH2ZRjNRuctdnOh1CFuj3xWAbz80cmF9VfgoDfM/3eLF881BqEu7CqCzsmEc0zvId/Hoaw7+d1WoIVnnZFMqLYiHxyRLrokfFDl4gVP0VA+f8ibJdOxkH7yfFL1pPEE4/g4zTrCLjVoipRKlRgNtrIHMPO9YVP8bKRqUXfZYvVnEvAeJwSewWNY06x2jVaiXp+R+q8wutKccXdsQR+TdzKKRBKKEtVIlRPI9/q7lUt85SNYj16kxxOWd0JusMpkGJOz7ji3SD2z2KwSRSIfOhc0tQFb0+6d39ymPg6ZXLOFRtt2FXxLoVCCpG6fD+mzD6ciln0PbMuG0T60Ak9Q5fFy5N5YquQoMf9r50XJ6EDhBMudNVHXSc3a0ihAvJni77q18MCtKKwSxk0V4SHyKR9WTQQ9IYleFG+MxZ/vUT1G+F008jQW2fo0y38YMDlN0EuXsXGalBDZf3Yrtb1ONBjLoGNiDj5rK6L/w/mN6XTwqyx+Ya5U2GmLMQtnsraE9OjDCPciksyyWr2jzYIcE01m4omTJVX7tdtpMbnus5ibBFDboryjPK8wejiv3RP7aUuHIFg19r7wHqkUIb9XPKBfAKnMyRD3965yewX4ZGgQJ0It8bjWaRVQmhNao4v6or2A1wLyIm5SGEzkXZUu/g7yCEhxPov5d4lBM/IGPHVI7c+tr5c8ABK1XqX+nFdSFyVSaLF6juDWqkyEPYmil/gsMFYUf0hTy4mRK2wK9I7Zj5rmpJN1a8PKrg9N2Q0jskrogtFO+3qafrCEy7LpPI6/I6kSwhGNVQh2tr0inHRw7PgbKY0Wq6ySPcTv/And0ArWq/fxJPngfosoRzdgbmkt3NHzw35SIXZjb6bYyGrXkNA9KS9axVNkiWOODA2yEEwKxrbd7UAVDAzGZOROnFc6zsLHV5HNo0Bx8h8w+Bw8uje8fAyF3JsWzuSXb1yZESI3W6eTLzpovZABB1LUQ5e/7oV+f78p6isaCUOHQRrdSFuvNGUrX6NaHfzfngyafHtokm+WmDoYXlqyeweYD8gQlvRd+q7JJZhFGwrrai0y93w0RLKMQXX40+Pe0WSKtIyoiP0TnDCvuf4WKzGIK+r4QE4BcmXLO30g/anlURkFY0BT6dpB6L4KHgngD32Z2N4UptS1G9g6fC5EShjGv7SiPgoE1v8rrnrLpphaAGvtO1VPowvBdPEUsAI6jzAv66Fm2F25ZATwUMm6N8zy/42lWISydAOxhmaUxCNaow2cSntwWRFeEy29cFbeG6y4hgMgGGWY7tAg3xZcYFgEV4k0XPx3QG6ogUdty5qLGD1wNbtkTHjN/bHZM4axMZCVH2pqruKLtZUE4OtKMho0f9K5fXMnvpnZAH0/Q9DEoflsAaqcGTxL0JcO2lvNEZWHb54m/JpwDrKxQHVLrJ+Arvw1S+TZp795Cqou8SvyKEJ1iY6qOwa26d8h5IMQmGejTRZnr4rp7zbbmyhC0swljYd5ACkuZdyjmtmC6QdrrmK4DH90kUEwov5jJgdYEroiCiQXEsGZ+giYEOeM3oAdmU7r0tx4ljcZ92PQwR97hV9ICAbCaVV7Jn09Qq8oa09FCdsLJ1v3mgyReYhzVNrqJK7vSSZzKS9dPuBqoVyqk7/cH+Qon17hgWuTSz/N6dX2bbOYxAWJ5EVci9y4s29cclYBQqeq69saS4SeSqEbCMfCedhyZkwaCCXczV7qJeiwMb0ow6CAU2Hx7AQaDbiwGzK8mnnGpWn7lJQ2VVGn1QQRz8+ffpHDj2v35ziPMbxlfJEcqnBjVlns6MnBEPC1ZqmAvvz9Ec+EzGOi55nMP4KR8CM/EBVEYVrDATJtqjtrkV3TuTZg9huTfrBoC1l7kdwIzJ80cAkhm+HnB/MwFwNguxAfSIkbv/vHRo8ReiMOUzGIe1+K8bRygvT9KhVwfWTLU/atlZgA2tANnw6kJHJxBAqJF87Slcn49t0ZZ7xXOT/LqbZ6kv0y+o/vnmDfjqKMrAiftl5EGNY18RY3P7forhR9ZIMMK8pjFyJyfOW8BbsTh8FtzJvP7/JFPb+dkD1/7lvL3OXVp+OLbDwAB6W6+5lFA4wy8PRYlZafepKf4YW/pXMflKjQAC7TOyVyYFmudGSmJRW2sSJR1CQxqbZxIHor0QJo3YeyqdscaBNGpi9M9lRSMw3Vx6Pbly9Dj+6tTqRsnmKZRZ8XE3HjaEiOmkU0bvKH2BE382uvQj7vWCcHzSOpsE4/R81It2KzizfmSGwTs4MikPF9AQHRkt8kcfeoCXhQKdd6iIWnOtXAngEYy9Q+Xzs+bZkr85Y7nYq6vfgSDKVYJzG/zmUJL8yZVl08p85ZWgvj8wyupegXez6PCmPdDHOVkOcywmNwFtxjxmVP4QU9IKX9/D9W6CpMRUeBSRKMjWuTmjcI3pLQgOIHDMQ4PDZ6wV9cDlxWLIFJXbFPDNtjqMADR9FV5XOCqrih4jZJ46p/qw+t3SoMsoNJ2LplJOfzReKR+IwKAylNMbp5t6evIOYpk9QBF9/2fdL2AQvJ6CPJEuWQcIEhObcyrzSWnklQtHzwwQ/+Og4B+LsEt0DD9Qut4DUFmRxV6lmMZqIGuuRgXJCltxfg7HAcivqjC0BVp8UM6X8beJULLBioKidpAKmDWiH5E5OwA24YMroHUOl2C/XmbysKlmvhgZiSsnGMaMe8HGXrwSZ9ojz/B+kkO05zvZl/Qp0YMwvExdOjaftz1r+fLvO+F/HXjpKnS7t3C62dWY1ALera7xF0+LIgssOiJhOJH1WRtXBZjXi66xQ25qk1GN6pn+Zr06gmCNzJ7MVeog8tvC3R4iTQUW5TiN0jJCIMMH2iSzsbM8KplqaB1LBO7K9rv043QQu2UItzQFo04PcJvaMQBkOmYeeK5GXgsIqtKiyOwEmejnz5TY1fRxXpV+/EEasiUWci0C2N/jxE0wqzM+/p7fbxThNBLIH2RyTIMExccDDxv2G2mHdzutK/QPQGkS2te27HST/WlaebpBMHLIXUK1BJAawBax23aYG0ZX0tVe8Pu0TIvCUUspeke5f63IDwIFI5fXgJgwFnfr/TGcFabADGuhG7G2r6ojqOExc0kBn4096alxGgB9uuxf4GWedpksXPoShp3gttdCK3OMPqHFdRIgEvWhhmmOvt/g1Tc4PYaUnQU7w3QRhtZuOFtrKoio3I1StNwC8WfQ6Q8lFpfIiJGONPN8SJqd8OMM8DWENBU+n8fpAvMri+PWdFplnsnDenWiywpW4Jr8wDOLNS3OeehccVjPmgp2CFNH3l+Y7KOGgOdawXtF8vuMax2KiDsMS4U1QOYTMv6r8iW3DFwfg3gZyNFqs0rP3hzngl5Lcy3vn4pZc1IaIRKw39IOzllfUywGA/5QFX2dcxPhCTwqxX+icQHm9cIdvqe6oNy2QDmAgX5W7gagulonRpaApQIeSTmvPl2i36dWqnQDeTceeeqmdPWqqUh5Py+HgJJzYWc98QNhF+Ll+g+rfs4aKVQLVxjheTDxrsH0JTv35SPv0+5nN+6LmmAkXr79g4QVWr3+zxV61LrObveSeVWD+7OVk1kkYZr8bI6yPcQt0haSxYYVRlqYMpzyw8n8L9RyawKTa+lkYjZZjCWtzRD4TanAY21hpVAOIwOhBXHlsig9HJ/KcT6s0ezAvgzEAqCHD4qQI4cK9BN8gwzWk5eFOmUx+3mTd3j8xYLX8xXe22pxQhxOBkrhtdpTgnaw7MR1t8spphsFvjqQr+K/AmKJy1EFPFXfJWtvNnJhNOB2K5KVLF6MFEwK6Xb2XpjQMAHdwjDhKFN5dZfOG6OCCv5X/NlGlEyRi0rH6lyqpqy11r4V2g4pdpFOcqKbReDgyJifCPmZziMK5AIXQMl2/P8EiCRb1QKLx83DuIx2tj+N58u/ZIzBiTkzCnHfANPwe1lOkQJRWq9gDUk34Ba7FA8buT8YZZ04ZNgq9lXlBYrL1zwTFm8gWC1SbpKS09SaBa96qQ6DID3XyWPdTBv84WbPKz4V/ky3hS5rhEa38s83EuEGZ8Bs9DLfJkQOV12XEyQYLOUbEyu5m4+H/8VO98piII1PSqmdGZvAx56x0DH8yTfTFuI421grtEqAmvR30WCsOfUw0HPUDFdmb18JoktQmeLBFEge1RIn1mRMQafaIksW2CM1CdiyY7Y/an/NX93EY9fZC4Zgc/CP2UVg+ypStInvgbdPd+h7EW8+JTCgRuNxf+o9ktJ19Z4mUmgJV3JFfhClo+2DoOoftifQFab9yFecSYocX+Lp2tNiCJlJmpmQE/p2dLTo3/ncwU5l3/cA/gzRVp4565tUiYo3owEK/U3a0Ht6/Bbju786eJ730KohblBaNaBfaaX1OTwEa0X5hvV/lDoGXi4IpLW+rsyA8/UaaOtAdnDFIqqYBxlQN3SRLXEUEzjzQtJYwDedEX8nSdnb6ddgFdXhMuJHutwl9fRTQEI623BbCC7PqT/Z9nqYZyFd2lO7Sw7kvMGT37DLwKGHQX9mh++Ye5qMhBCDGGPyti5KUNAXXsuxLRjT0B4V6gNYldeY8c2wypf3gaoOWwwNpEm2p8iua1/T4WZUVLlyPLJKzlFMBRp067ydeY4ltR3IqP0B8hJSBZP/0Bxoe680/XkoWpomt6KVxHB0gmTpuCRl9kBWLzle/UzA7CSMXByAnoslmaOQqZAy2Mpsqpmg9INGhqIUvLZUnfG/ENbuS7szyBw8kbi8J/6jKN4ZC+oHed27EhWRqMO4NxCKWeTjwTTjon9jVExXJbDkhVhi66Z6TcD97jTmiF66S0yF5VOZPX61Um0XZSagzg2ddcs+pfd/RqACb0DK17KJg+kf9AkCoZGLiXGxn0g+9qqxR4tNes5ZKPRA76l9btkXjveHKKAQPvmWaDY55R3kXgxHxeWJCUKwytVvLWTVEUAYtMRYtPZ9S7EKQmI/Yvx0pdWeohGLSX6ai+HR3XyMXGqaJK4YSq9hkSE9lGzTTWiQ0wKbAY1MRLQ6UpAb6wDFf5hEljxGMM2sXPjrHaXixkZLctKs8MSsDjcFH344F1gvp7i2ya+WOjdwGVDwHJNHiFobPzrmvi8ukAz4V4+u0XE7EVBWl8nq4ChG8O0NsauVPwzmICpK3nUvjtpfEgnJpROw1gVZqPGOKXgIW64BzfswsJc6f6EQcsqX6O5fP/u1nGM0OHD6Zg7Bz+RHjN7L2bG+DKzX4CqBnDKs7RODLmdldexCQGleoj9o/Kdcx9ghnyi7/t4KmrHFKIjWdSWdZKaSnhZbCDJeGlqhs++/RuxLHRLKx+NCBPW6jwprsc0f9HQsQJJOnhRbt+zDcC2SdE6C+HRUdW3GSikfuYyh44le7CbO47BG9PKBHYoL25e96Vpe3ljJPcc89vyUqAYsfDubW1BUUEE/algOv7+PQOG8QwH/ttHv2eaNkNZ1oTIUPznSteLrQd6fTJX3ULqC+fpTc2PyvcQq29Vu3hVVXfBneqFvxCmi3rwn8BGFZnFiAIAon3qm5/WNBsItzeYQ7dggCFBk5sI2D8youGWxEwrr4+UEP/P+ee/W/k/T07Oj0AHhlJY5uQaEKgNnOBmfXpNTtM4yhZ1yuVVh3bubf7o2PbqWFebuvtk7r12WuL83kqWN+VOmCyldgtgPUA8wt2KleGQcFjtaQNXjCSSjOoe5A4GqFCm43wCtP3a/9aX7bk1pyXoVIYEf7kJhmtCL8ZthV3MXw5zMSQCeRgLTwJh3/el/H8pW13v3gVX3kgILp92uJi92iMkb3LIvtsKM3WDMBhRZ3o8MW10g1DxIgDKxwl21Sw8lJZQ3T5AFzp8X0dfq2UqFbCL4Wdmskh1t8RTZ8HJcjHYI8oDlLcfl+u4SS9OVLG9+nJgHCT2+ei1VYsBqQOsOnFRLd0Agmf4X6eorn5x7X2DM3bT9/dI3YEp2u0Ys4r5XWrZDHZ4eRDdGXn60PdmEPeu68FRDkW7Qh+roObW1ONtakxyuW+O9+NGwb+Q1iYR+by44LzBtPL6kELiVSDhWTWLYn/DH5AuhS930E1y2sILHtYmikeomhZb0MGfC2MuwdtSE7DDPRPZtZ5YJVw0cqgPxT2O5agPBxpzkc7eamnIsSRjWCeE5Vq+h1LYgE9NtY6d5ZRjLr+mVxp1Ar3v8+aRqGzjYhfEKgJaWmGI/PDuWYr2wD8P5IeNUn/Bl2YZclMesZpS9YftEp729sSOBH34THyeXavr1zu4cXQlfAln1B5aLgU/I/I7ig0Bwo0h7XxnFa2SxQkjy3WzmBRwXXqyfZh9WKd4rLUc2sKvsaeY1Jg6stWX4mX5MgYaF3DjolxK9v7cAml/SDxxCZYyO6SHMxif/EnL5pJPWdrXeS/e5wXbYkDi7E068/dDxdNb2p7rpQRMRTNPSQDlNL5UzaKD9Z51f2l0ZFSCAayxUl/6Mvh407TSaw3RsdnxkCAykhFfn4pq/4azyut0zf03RlfuGJI+SYWg6jvNSdyyrUllFsPxqB1tRDBKDAmvaLWKKB/1b5AgAgLa0fZcPtPbl5G9T02pGozcU7I0nSTBvIYxDvy1x8Soit9dTgFoZZL62WWlNrg8Jg6RnnChRUk/E5PLq2bkTxupEtKuNnGAKfEim7bUAjkwJKe13c+vHnLfWUoalgCgogLABVH3KpxjyIFqIBp6jiT/8hMB9yfQTIZzrUnOxEqP7Wu1OT+i2/wTVDoIsuLH2I60FC1kC+tb13/I55EEWWdxzdY2qIgVwEOVkjIA0nJkIkLZp5Sue7d/aA/qC5ObbavhuGKGZYILBArsRzuk6z6hKl0+39H6YcdnnCcm/snPeUNtxStK37gIQH4tKx2kriKAwDgQnwq/IwHwUSc3hQ9dRccN+ilGtoaCY6ohIUykwOEG4XKDD6NzhtWl9i/6pA49Xrq4fC2Udn1ecxrVReq3PM7TK2RYCNDqLWCtUV4vJVCyY8Avf8sRCVKAn3uXdRzKJCZIdIQzBmBGMDdB9wRuaLbhpOCZgxtWqQ8z0mT+DP2B6a9aR+P/PTcDxHEXwlqqmZc6boVWLHTxWvyEomw35IfLnXou/ZdxEyV2Cqr8MEXfbjGTAA4KEeQtciELhprD8oOWYT3iFw+nJHQVNz31kStQvp2WO/gUko5QU+hwGXyRJ/UsYVE+SA1uayZ6QlxWWNXUw1SyWlvenrH2PLChNoHhOkBzX9mbVGUlpbfUS/rjHLpZ5OjD/VdsGMUGzSoitBLLJqpI4/dDQLvYUxMiMxNSSPnXmeP9QMPjv86ASmE0/cRMOSh5KoTFx8IhLZP/7mS56bsQ9F/5uveCjxcMpX+OpdY+MuQifnTXK7I4BryAm4Bjw0Kg2XHh2rghMRPOYsIECVbcj6pXcmwIQSYbF7QTzT3lFyoA2C8Nak/bc1QP1B/oZ+2/Iad/8Exw9B09ay/x0MSI1R4Y7Md9NWP9+MVz9Jkg8FUnTQ2rBKjOZQX70cOzXZ74ggrx+BzHra+9M5+VAWBoE7oDN1/c5cJKaYCfIPaolhyS3xIwuRfjGL6OaZHdLlRvcYBRlI1K/G2E2GpUTYY/wgVoehfCqY8pZ4UDTsFhU1GOC+N+uxiS9JoQI1+FyDMsgb7rJZO/CVMv6o69iKnPaxPaCt5+c2Dad33dQCAopMdsN2cItE2/tRAw1yNg7nVB6jMI/87cW/L6RF7aQdYj3aj0mNmOp11Hpg7uXyg7WogCJuY0CdhHOUZzsuBVZ2SuutvKRagv55Zm6sNWRhIDtOgnZy8XbEu5UtyvyNRc7qTQHBEdYiNwC54IX8Yj3WycAn5oNk1So6Uesfnti9OP/FrqhBLNm/9HVzYc11WhwG89avztTdyeGv5W0BZCYzSrQOHkca3EPdaTF7mnHr5m1KJiRytPACXdpcGrmuiGXIiJQMK7LWbQwkuJ4bVP1KsuoB6N25vHQhRANFTqYmtg7pCHnwx0S5qVVBjzynrSIV/IH33J7+z+VnW0cMnfHmah6chzLSuRk3gJNIyWdVWLHUbDn5ltgKX1eehfNRF8cEhhXOMj6K3lf4zzBEcFxb17JBi2r1Q7nhOPCGytjWedKFth/j3hm4t59ptjIV2A3Jq8VkaBqYGxnr4PTB+drLFYImAk7WbiqY3A0cMiNPAI9UKz+rmLtLea9oelJ0Aw49AlmN++MdC94NBmphrDdQKz4PF+ejnu+HqFqDrETUQiyB/Q4hJmu4BG8CYV1VKP5EXwLZGzQgMRee5PgGOAvnoIzP7dRGjBTkJmfMT/TghPylI7liIUnb3+9ZtOvBJK7Ji/DtCGR4LqIh8p9zE/5J6qDWiq/WZb766xKTtuh+hXjFoHYc4ksC9cNADD98lVrKM3GyrzTgaSRjLSD9MsXNv85LQNGM44eWU2zBh7w4QDOSVCr6vR7SfcyK3sAFZTjmUiBRvngQ7fessaBGmfhOt6X2qOSfHlDCVg/kBokjQoJGbwx8c36TRMd66/QEAze85yotlXIyy7I1PKUIzc69yO2mQ7Ug14zdug5E8sGAcuaNvPiIPBXHpO5MlSs61k3UmKJYxQI5qJb39fT/IBnyzKJTRkS4DnNfj7U95XtI6ePkO6+1TKPozrLNs8exJ44Lmu8buiUJJ6p1W9NqaHB9zmsY2bTUff3K4veCGXQMwMZhKIA9DVUHJq4k2IPjg13iOIlaCcFwAS3Zq/OZTa+wMPQsFiYw6iw+dfsiJXYguKWTzsip+PKfHpBJpJ2kVEW75O4NtARb32IpxRScSxTnfql9aa10F/TBWTmnVtOLvbXVXOnGel6My2Vw/yXv5eUNxxl+63hZY4mfZeqDFFwNn0e6awS3zuapdG3edbPJJD25ieZ2yDswG8aGudMYdt72I4Al1iSlT8LhfzvhERJXyTQA4Cj10U+JAzlw1fKAvOPGta5QBQiU6tBAnfKkFTsP5E3mG0jJ1BzJn1GtrKkwQ2SXn6IGAjKrsNH1DfIxXo8YtlT65gVC7QyeQjpb8uVCU2KUIrmW759BNhQpp/SOFhAzFz7eoL9Ns7URW1Y4ikDOOmniMDaIYptSR8GFmcUsLiaH8dEq0BozKKnD0loFm5YMvH8OkXmeabOvEQ2eN0KrIDBOq6W5xlsKzOVwwk/S3v0sNt/oiHzbGrD40FsDgTECpKuk0p2WPLjCCQvvtg9cMYoi1m9MnoHJdxP7dLmtZ9SFLntPnVeQ0cVvbzQ5h8zvH87rz2H/zkTrZ80zvrXJo+6Apa5cKirsAxzmpW0YSoPjCR7UKC/UtE3inhqr/SiiNqE+a5TpwDApYGMidUXwyMcqOTEvecZWR2J3lvHb4kNpI0qlJYDkraybyf04TP+kX6Vq593KIzJvVx0T6d8P/80p5iBja/1Yeb1Y6HGb2B2CcS3kaWNXEEQuyAa7GaQUhKSGDSIYl/P7T+sco6qOk612CIT/HJsNfB3tAyOdPkXy5ckI4Gr9b+D/DOZbRQKkw2HwVXSMZLi1VFvgmRjakmIvpCJzhWvF04HbI4jICFwRKSH2Yv6rMpQD057o4v5UzWnm8HLaFCN7fvm0m72BBoVbwfn/ZGtUvGg+1ZNkpfmk85nS22+2YkJNYyQFoSIDKpi50/4JyulgFWZ29MaXnzVvAD0eLGuYiM20e6ZQZUEZ95n3aadVoXgyd8dGu/b4zJCYSk0CcSOhJQJZyeOApSmoFeskD0deSqNBOuwiwDYNVr2TvgqqHNWG4FPeOOVpRw+cJCR/EgssP6C1uGu8Y590aPhjGND19aACfbr7dEvoM0bo/ImRTQZy3ayplHLz/sp/c3F3L6MFXg//TqIoQ7/jej+VUpOZgnwG/YoentTvca8xQt5QyRNgme4A7uYVRiEXElSHzFLNxvjxReuGm91HF9nd9P4d1K/dhG8l9Jj79rZJggjKlOaknftb39rCLQvfqWI/+YW7HNPKJ7VrplMmgtEAL5+rpZmnJmYgpBBSb9qJk9CuNvVKte9UVSbLKvtYThC0Vull3Cd9+zj2K0tuvS6YqseMtPRgxZsRKSVpDsxmF9sSuONVP2NXmFHQekNiS5b41Q3RLF+GlPLiDg3t2KD0Cu3u5E3PLypzFit7wnLTvMGcFOtK1LElXcns5lCkoKKRbqQKcDlUhA+FvasdU8mR5SgeVCAAwa8lcnFQU68v8Sblsd00I0j515N9DU5+zT3mTkUQCYtwfxkHeJ38pnlSM3r+kIiU0d9z9VWHWqrAAVyHNhVY5dAYR4qeo6Gdv7ksMyiNHuiHIHRdelqbQWoqsGKc0bzsbHaaQqTIJg1AOaMqtWsEfw2Fs+u6aRIVb6rd/KMhDzWSdfQL9GDfWSw+GYznUS+IycABZzA42uuD5eGAJeuVJaQcZxAj+4eZ7X1zYqvTJhFdFWHYzBfSXXXA2wMXplcUN2UTWgClAt9GupviZAd38LO1oc+NVVClgUY5V+ltvKV2wUVN4tj8gKnR3R1F4YHPVfil7sTzd6bbJlGt42vBZ658cY5sRwcUAJM8uneuFFVT7KSeCA247/Mtmi+O5lckVGJHy+rIM0IdStlGFOX1yk0wJ9zr2lZl3U5Lg17iAPFOkyzde/NWGMyfHcqPE+mJX4ABx/FjvdjtSpZFuIKxGeSU3aUtG2hIOCCvxbzr9s6jBGqaDVTaaobRRCe+p6celXP/Hb3QPlhILnPWtdD4+STJ9Q1ruu39SqFhvAWXBM52TU6bo8eM2cIessvUaOXagb97XV5OK+p6fsHJOOwcTagDhK/rWlYjoqeAUVLI2VHWkarJA9jvt6FYyqOwL9laF0/20YYqQDPn8Q+erYTdGxY6ZcH8QeGOdMhMHucKO53TDxdV5CdHd2rdtUQvczWdVr2/WpDhSWe8Lti93kVsXKtQTpgFwuYXIA+wdSFm3OHkkse7c8FrVp0UZK0CjLj9pEu34Du1+DZ1Wzd/SNWEWAOgSCDNs02k/Ha5mLQKwBWamnSlhBo3rMef2k4xbLUqVdoG/9Xi6i/D9NeCSOcWA9mn68HfH5N0Unwp1RdD61iP4HUD+6RSFM1HiDbmwlfwUN9nM16M7HgrcZN8vUIoLqI2o04mrvdu9nRsFIxadOBeJwb5VKjVgQiwDUBdkiTP+2nYKEcoE7bJwh8c5ILVJMTFgrzTepoyh69fwlHDE7IK9Qu16naeM1AIK0hmsfoPdJ3klfC3WQeYYhmxdNKmgjtOVCsAUA5GBk2F8cLxIW8xPFFqMh9FRJbqvpaH1l/2ek+gl+HV3gRhjYPfaFuUb6B3S9Y8rPpZzoOYmuID2NpOA+t99W46K+3BzExnnlnWar81WprpVvR3UY13Sft2CIsLblkxOtksn7ZsFO7NuJqdgqYCscsdtBCYRkqbHHDtWu1h7VUih1RS7uRpTkYndhU6EgonpsSlE20OBLMRhkdJbwsqd2xpb81/wxRx56UfkaDbGJbNgOQFm/pmLub0r/m0SA2R9nTET5GiBqvkbpj9D//ftiGiWHMfYtac6gTHIgJIY3GCIF+KTH+cdV1YRUoWz90Ifp1VTO/IdBFRV4vWZqvQQ1UfhREwvy+wL7wgRi+TvTFapG2OHngUqZrgJPQKurOzb2R7cdVOlGCtbROTA23lY5uAE7dW9xcm5tAj1lAXaJ8vxvVjlHK9+LmBBpZa4EJ9kn/WKp/SHfDzSAIBAy0n+Pu8BxERGbRT4EmAAhavxk+EprlAGTQQwg7uEw1icep/fO9pzmZfNIDHsUXZF3vgdnOdKmwuxM2gjSKYcODpzDIWzUbR43ltkNaYONjmvpnSd0oM9bOTHt5j1G5Z9ZV1cqDmOW0ShDlQLbxP6P45G+JbcH4GplYKvz4iowtwo2i8E0oAWKKJRdm3M0Yu2WAPSJq1mf6JrRv0cZpNimG2YBSFJFcRdxOhAAdvWuAG+C3ITuW3bd+toYBQXSqjhjpQYcXHJyqmKw869WBX4EbEji2utQaH0Vm9tWsuMS272HCIEkkMS4bXQYE7AKk39x35gz4snIWQNgWRfJDrx8hewYzvfm4Uq5zD4AorUZYqyfHphbxrWPGUvSwP+4BNe3ulXLi2r0DfioZkbhFV282cyHgJSR+6FbOdeQ4S4c19h+PKByq1uXDRSXC7FGpLj5eQFJg7/0hRJXAhxXZ9+CHnQjp7jqGbwDJm0P/BcF0U67e0DJrFxFciREgoPhbfWitArVGC7xf/P0nNHxnMQrn5ZtmVO/5wH79t6ZCTaiTvLdMMyHML8ymubVWkG9ncX+1ywARre/Tfo+5IUvA9xb6lwG3F3kKHv/BkBBQjhH9sgNLxNck/k8PiXy5CJ/66AMskUEaMRJMAFfz+qdwlaBeuutGRjBuXpdR4pFPrKHmmYfQhaOLpiqVw/zhAEMIyhlXKPj1vPqI46Vwipou8MBnb8gzVxSwc9YSHMPBj21VlMLZkwSbkAuwdIIkB+eNfvTsL6Kow3DRrl3VEdamoTFBD3CZigeaXlrYtCazdjXSQ+UxBECLqE85dUz3Qh7uhC0sbWhLk96sE4pnrFn3DPoYhC/2aqX90sFZH21drBs75VrZGrGRw96FimVnkw8O06hYfqOInQPbbKQdBXD/i0cF1SxXtjMzUJWtE1VBoAUiTtX8wCzEMzzoTf4vODBgWNX1bVrcoXi0d4zE3mTlO+4gRm9Bea1ACC/cyGIyKRivrTd/pZFET47iGVWMHgJnENDxCzoKuWFbXFCsrDFKKjr3PS4S3UgJ/3tO68mF51vnkeSxf1uABwwD+D2Nh5pf0YscnFkUklE7SpbyJzRSj6NOqHwb4vJkHsFtXjDBUukvpv43zwB9LLwBR1mnvikG3a+r5/lzMDOtJBI3eeD8OoSJw/QpfDVJdk3efVQpwmD6HHI2GUtkPj6Ib4unb88jnB9wZ+lN1YZjvcOPZWUehjSvyjoq/+nZTodlPnkwLpm7Rgl/08w56RcMdn7ch047DhpLx1QIVaVCMClz9k/mqfDibmhkfz9laaWCNbxApnRgKFtxI7Vp1XzyYnIXXDCdfidsWJRqQLw2hjcB566RHVpr8vx8AdlWCBTwdjzRKqTwC5RKJJLyEf+AHhLP0uyCPTwLrpqFsCZUyN16QF3Ue3UuRUcAlEBIWaBpDPlkHNOQyPh8LGedzA5XewYFiMy7FF7MBHlqk0Y7WW2jTzRh2OuASh3Jh4rrxgyYFIEkVnQJxZud11qjaN07+EjX2uMh1L6f/bPOSBvbuatkeWluk6N4JFytj9z2PCkU/OO8A4keCwssMj4Io5XaAJxgdWJoZbC7Tj/bziKp/blAjuS4vDndzW1PDdGZ2H4gQvhXChQAFnOctiQGCO5U7W1mlP1t+aP+LXHvykvETATDoOL0hnj4IWTBDJm7/XNX/KGxPmuf0pVnXZ08CoklGMSjaxk9elKRloLmjebt6NT7flbmMprU9kpzJIFofT2I8Jp61bEtXx8gSY7XRMkr0JCKraWGhE62bztRbcTXUk73UHEiOFuDEZe3NvA0KIeAe3mKsWfJOzdlfAkyH1w+btnHw/U8fRmyHJR5KcLFSxq0vSK8/dCj6+7YEU0GB8SW+afmXmS3AlT260CzxMlc1yxgCxqvDdUdk/zEoHSLhNxW0oqVULK93rRXzJHafBtRfKs2cB1dKkvrinHB+qH3m1182f6QX0KPanpQdPXBLBeLlrHwWuHuoja4zWvpPYrTy7s4r9FV9zZuyHKdqb0Wp3S26oqOXb3IlZoZG1DfLEXmOah6M6hAa/bWt6lF7kd2xMHwH+4qn17QB2YHHiDX4O1PGJU0bAl+DVyXr2+C2hp15lhsWSrQ+GSB2gyNSLqPie37lwbRpfFYZSvBFAkdtXolaeptvAiLM7/LuzKF8mA/KGP+GzlqZ1iDN28lNSmYYFHv/iQWItHwRzfBGJXtaS1im9E0y3n+SiW6OYg80xcs4h0Q8iGr4CbaBABNZly/ig8NrBC49tXFoWZVaEnP3MEu6zZ6QrmSZkBCDGb5fZDpBQlUI2ecBoPxoI4lIak3y0EjnEVACsjnfP1XU8BSpobOqZRZi/LEbIKNGnL2XL9uf7cP2U25oq3qne9ud6MCcqC7SHbsYYBq9CH+jvKmFkbwlEz0Pqbd0gKKiCuibvJnxoD0irPL1Myg8KnqexD+pfucUchtH9jzj/xzXvERbsCMq9yMw8ipKB3cfRxfa5HTmUNapyXuzIJekjOrK856oU/jEgD9Sy/P8SZ8X5Gy/bp/Wl6uI1LslePH3ziYYu4HkOeWPoG/5QsfvVn6xpxCn6A2TycL2owell/EUskdLlgAsNUsRwaqtj6C2x5mptow8hwWUadoK9wB6eykE1vYRd2aCt0hSIuhWdNAVRZwp8aucK7fLwZ+N1j2fucrfQ/6ilFfgckOKRX4vcyBWqsqceWCach4pfPk4GHY6Iav1zvaX5RVxKGfokc7a2tjqNdpQit4GtzgnNx+SOD80Hy+tDdv4kQHw8rlNI/8CooD4Nm+wiuntHg+CydNXDtbViCuAZl1Yc2SveZKTyTf4uSf6qRnDnEN7cjk6hUx2HdvdyMF7UMb+N34CiFiRbEsQJoeeqUDRWc1Hrrd4ktOEWEH6uuqgtXBg/NPldXarew72JMjS/LZX8EdhUECQZDko7hpOe0vtnNyyefV2R7QtfgJOn/5GlxGBMIWgII+JBxcNpkjngy++p7e4BUDMbKqjKg4vpzu2I4rl66vZFqsrkvyhlEC3iICBYoBcVJnM3EqEsglKIU5nTQVvEuUbITEsr34ALWaQG9rmVr7kDsxArFSOu4ZR8ml5HnhtV8SEZD8SCxwrmqGcvmK7DYZZG5+vVLuluRjommJQVaFAZrSFV22+xXconnJuPfPw6Tef8eXdjFlB4Gsm6iAT2fhHiWgh8I34FWs4d/ATeM5s5rlCKqTYwYNA8LWwgqQbrYMSkQrKQ5Sn47Z3/0WhrF3EQ9kN75x2ldQ787wIvokSg7gFPd/Le1lGqPwBWBxlfIf0Ijs9PqdCSnh6vS5G/vP1LSgq51HX3GW4e+GIQdkvHp1WZ6kxGGeqXQFbZE35vQrUVss7TGml/pMc3tcg5wGiOz0ujIGCfoUAmQ9fk+0hvRs/EO7xd3KVcmQa7VNaYFlaQBcBHXyruCyosp5pT8pg1pIhFuey7pS2nA5cR07iW6e3/bd7N8l2BnpMQ0Z7y5z/62LWI+MgQxVhYSGgquvD7yiso2YTy0K2Me5gy/4pIY/fOdI76eOf1fPWtKJGk93y0UDb9fYW1QVpx+CdtdaUQuI1h/EoDjQ3KOBOFaqG1ZLEmQZStMY40f+GCW5eU/PCLo7DFT60GrUiz2UklAYvAekyJ6RaaJC0q5KAXcq8G3UJnDLfCzdX8qpf+rh4rjWqaesmZ0pEskSrkz+t3/4C7+pLGyiaXSMRzfpTamKmlJ4rYvuU9aAIHzwODMZnd7BRMa0q9IVaa5w55twqqkgi6ZEp3HK0CEwgQpUK5ELDuwahzqaPIVw48Iq28fiIkUHjOfSjTu6NnbkJj2jd35O6nLFMAmM86lfjdDQuBqKVLvzoZ1vD5e45ZSfwAwStzKZyIIkmVPsH2hUAq638X9ceLEHSQBwjX8pW9H5k2NEWzZpC2xpqy4L0PmzY2DzacooJwa6nvUWCF7mMud4h668xPwjWoILL/hhoHZ7EPJyVKcN1VmNSp569ZRVuYlwfYDkRnimOgD/d41ewQb3ul8nGWcyiSvdXQPFl+elva4W/7Z3CRAhVGJtuXUr8xRbQOVf5h5R3KWyIbdQiJ0+7G78ciuAZbKzixA9fXIYLnhlweA1b2rTy43CXpnKINYl+PfRVd9zqJPdXNB58RJxJ7cBD5Z0upLkJJ0tQBp4ES4vcAiS0Ea6AwUqAxGnxV97VsFU3cZigs8dmTO6+j+fbLo0MF3tYyiAkk8D4wkkPyQ0vSYGgS2w8gpkCeOLTCSbbSiAI8FCL7SR6J7ZPqKRSoWIzzdk5zAJtw2VRydWHZ9gxpf1DQAQqBegLLTXA0JN62UpIlCF1LUZIvIsCwFDJYs+dYoTBskjnoB9JAPwJ8gecwXfWUUmxl3vodScQ96pT1OPXBLOyGzy+D93FlWHOSudxmLDO7qXmfep1YfsENVlxeVoUEOfYCCq6yYZ8zdTnBBEkk5jqC5wMb0LMM/JPPJZIoLF1Pzl0hy1Z3F57M98p/9F7q2ZGe8Fp9Hr3gmyIDCmUZswdOxqNV8Jsic5BV2Kx4fbFOg4Ajcx9UkFneCBNBrowCXSoBDeM7HK4vj1CicMQG6o/A/AmSJmAeJkDU9Sg5YeRaauplS2cG400N+ut2dLZIOqap6+9iuN9xTCMzeDjN+4QXqMplup6JPYuHP424RIbCNiTl3oyA4SYzC2MQdN2KuhzDjZS6h9R1wKTVIDOtgifAtyvj3iajFrNBWwi4bGZ2j0adndmTtLYEAyjKHit95+l+fmhHs4e9bzh79pJztLIvWAfZHmqHZ8e7TsNHcxgPPe8eeK4XSkg6XD7NBjfdz/+acz8OnGDgzQW+3SOXCVABOWzLEOW2oYDTZTkoh35X9lp0LUPOOnZu/FUIPPEpSnmIBiADjcCHS58v0I/vzir7hBjfi0fxLnhz69xBSo9C/1NQB89XNJCut0IGTnH5lJuloYkYsl8wqKU0iGtei7gkmAJonHOcrrNmfkMizLCmjYeclOF3WS/55vQBWf41yUt9Q0m7gYVRPfD5/zxdzO1/xQybMBFGvtWKeq8v3sAq0rhtomQWdhsBrPWdKQbVTytCskc+jpaIVrQHO0w2EfyICIgV67CpXLMM3zgJuU38/m8O5zj1tpAIUuE7Me9vBAC/KSZb34MdOtc6A9aJJbuD5NjNaT3apXla2bXs8baRznPfSsZ+aPw2aU9A9K6p8izvT8/gbdlnBGdedAR/T/FkJNI5wwF2xTIhr/u4V720NtYBqG/ruBjy3MgvXhgmtREB/Psx+GWzWI/ikPEAmquXUigKi63/lv5YRWr/upTkcsZ/mughZvQ0uY5FgEB5w0j1CUsv3f9pgBUrmMUOTSwAMV0scgBfYZ0i2XVK3cPe2WU+VaIRkG+zssadOp4u1/Kg3OBMPmKvLJFoLHWVqwWY+hdv8UIVJTkYuq6s/YFDgUW6zjiKmFryyw1YN1jp1iLrg61QgpKIIGln3MquiY9C5+/5cU+KCD5v9RgNw7xl46GKfZcsnfl60NM7jsZssgkik/9UxqyPxzRNBfnlYJWU4oZSusWPtUAjKi8N6LsgsNZ6SNowwaqh7ZWS2VlID9Q+Jfmk/0x8KX09JhTTh8EfW8A+uM8wI89YLSWlx4EfUzMP6XCVTUTQ000WOjBKUjN3zBXP28GjMSI1SYfXhSnFcvATQ7fjOoqnXVdAS9hwjU6kb2unLqJdafmSZXMDAdqCROEaONT2DinWA3v0jP6mXBHKMDQrU5wuw5GSlmwUfCIy3TzjKyiRoIASa8mjTewJ63pltDsQlY7uYkBzCJQZN9UqfYIl9pMDw25ySYvKQ53+Bu1PomAnF63VW6w68z3JDhvtWv6MLDj4SbQ1tmEPyqExT1HpF29egNKlsSu2A8d6B0eBbenB6REkbZ0ueYaUGLLCol4vfctWaAXwuKQr2GzuAr92c2PGyLZgy4RwW8rPCzQ7DVy+r4CKuKKUK/+ssRGhmJySylk1eFA5XWLD2zT/rZrS0I1KUe5g5pNIQTHLpk89bPvwoIC8/oeL1Lw+R2AMomZcQ9WiVqsAvm/9pNln7gzl+0h6x1vvoVJSe/7jrZRK7CB+qSAcqb55d6VIp+fLvO3zDzxuZAU8l6DiPCMj71PKVazilPCkcUagBC1JLoRpTO08WgocJQCdLvN+GJ1zWcx00dUzuUpTjrmxCipRLQHEGLZsOL9ZOKL0N488GX4BxrG4lbCMSSiwvtoQvrgBtSdQ0aRCux1y9KKvJXDHxsmJLJJP0KLsc45M/CMGCSlL3Y2wqvNYklIxuQNb5IqLEpifLAB4aimsNmVEnnLT0lVzME8MieB6WUAgzdjLZWZfTdOqyCxA/0Kvg4S1gM9X6wKHO0lQ9odXwcQRFH6K/u5gkifkCEl5FWRGmYMUMRH+FggqdLrFqof221dchOWGoHxQcaFkB9RF0wpRFYhBWujNuI5n8vSvZy/gqGmlwNFjibU1/3cJQRF8XSWIvuDJwnr3zv+zQOAD7PIm51N7P+7AOI4lqp0OsqcSaCw8Y90hi3H32DAXpqnPE87vg9VrtzK0o2IDBjYa4Ow+P4FtFvJxaSn8zq5U5Dd9VXSisZSByW4G03WNKGi0v2dZJSVnQuW/M06pbtVgjJsIPAm1p5REoqwVtZy4Ze6BPMQ3oON2qyyeXeTmJZiK3+8di7IemLmpxtesGAXBI4NUSt5k0/DdyCntZJ7CyKkgpXhtbJ4B9xNte8up+2VL4d9dLqJ7lVHntgpj/Xk6C3aAg543UvykV0oLH0SkAEzwQ9e4OGn4neZDuWy9q+PreaH7dTmo4Mlt+p7WtUXbvrrz6263ZfObCjj74q2hizx/fzlCDSlxVwdFRBuxNHm0rSVC2ycSjfpU5JnluTk/WMbXJbhyWHgxm/wz/BIQ08uyYuKAd+BSMj+G/JZZj8zGC8t4WoIywA3c4HfNemkUcGAwwcrkFY2R/AThH2zu9fphuNYadINnMWfTFKbHTkwJvGuQhbWlaxvRW6+4xtb2H8mQlpicMWTpW5oBVLlAlgTV/RmUYqIfxDICT7GEbERkM3yPTVQLyUI+Zyg5Xg5svUlygT8QzWArv/+s3q00GNUKNn7S15RrFfTj2doXrcJw3VOFGqLl3s9hiDZ0aSr1FBeOtVOi5qM/u91KP81BsaXgTsJJSCeLghqTn6ONYSou17pPMYG9kGlzoVygKsuOlaUGFdov9IJ/4wSljHVfkW5v6N1hhHigOInc75NqO67uPedNXjlXHNpP10wuoO3uAvyYWEp9pN4fUR54OG2oXQhoVnxf4etNtJNZMQPMAo8I/YLz+NOiELiKD9YUZosKY1Iw8AxtFCXU4OdjvZ8K0RtDLFAwCZeKh4R5vAX5IkL6i1L2nCMymOXbmZWLWmeZaZUfwUvh0eQl26cvjU0JwT3I8SCb3U6u009OBFIj5e+XEfRLP0nLLlQZIEHfSSlJPPalH/aV7nALDzd/BBRjBNGU9nmFTCdazljo7I1fL3to96dQNwPNfmNdbYZu0zr+RlgiZ7ldkfpWApt6uNRyMtqSvR08YwlGXtJnPF/VYZXzvu8nR+9D32a33Ef0FbQQg/ulgRv1OgP131CrrGyzyIaupz7DWNfnVZJAJlmI37BULHcIhsKMEhwhnvxKmN1PO9XVQaKR8MQ7yW5hefgi69g4pxgOHzEpt0NKgRIlsWsu5wMMkaUAzac9I6Viyk9KnUNe4FoDj4sRVcd+5P9WYFbmSmlgsq0gYTYxDPCxqfSKlwELOSmGzOg4jdji1CUM7JAfr6vD6nJZ0Vw6PXwUh0hkzl/C9gCI5bF5wP1Db3fUfk1oUafi+Jhl09g9jLaSkY1skJrVxBQ3D5DAZcIZAT88My8VK0EeYAEnKlmtUyl7J//WBRTE4kRw/Yuczm1EftJqm7Rt49TaIdGqAW0rPIv2/NR6KpYvqGlhDOaqHSyn22FVvOnzSj0seaFGUWkHAR1mgxZ0+X2icyYM6GbkpvhbxPLWR1xwfo1KO1cesL3v56Xph6u1/jCC5+XnnwjWPf8r59zeemR4LVTebjawlGyD/b4ju225jDN5oTBUW7B/SGY5UtJ4hALLti7Het0AaulScC/zxYJEcRL9Yp49EvlGAHm4Y/qFN9OUBvKOHYLg30ue3yJ3zmqz32720mayhudBTP6SKsakWOoK3iwtL5GbyFe64KHFftjlC3h2Q3WboQh9828asuyGJ5zdlSZmLQLq5ZpdHqMv/X581REFPA4V99q89ssZu/x+xxnW+CjNxm4RD5sDI/TdBqOQ4bI/xQEv8DG9wPVJW1048+ARYqn/13CpJ4joeoeHg88eqwwvZwOoylXZ/fKNb/OP6CRv6/ABBj/iA+sosFEcB4SKKHSrpjMkf428Uw4e416ZWA801ELIU7wbHSVXjS0iRj/BOnXE5iFmE3okr7pDA61oz/WmiqK5H6jifYHnicVGb9kD/fbPN5F76m8n7XDYiajXe3/6TzJYlWFOeWPkRauMb8XsEXB2URjGDLF+Qcj0oF1HjHJLb40Yk8pj+yNn4gyM+6yKr/m299lePdYh9wIu18cv4P3k55V1UzuPR4PuHUEUQgv+8+rseRwlxK68apqDKUYlYXvxlNdrfRRWGgyetWCYTAoxB06pEIhvmQ8C7nsIW/9OFS393m542slEK3WP4GS0NEUAb6PY8ws3aZGvthBx+nvKgKG2eL2D49pLB4DIkcO0nm8hMQ6gf2CWUmjBKWTbcsE9g15dkiY2aqdlnXJqBS8ANuX+g2PmF6ryCuBB/2auBZ4kJoR3C8HJ5D7/NpiRjBvdk7p48qvk3oDQfxVN2W5Iktad4zCylmURRDJ0M57HsYsqMpXCCXttPnUfOsJvb0Y1iXkDd2guWjZq5sdBxzixW0+UFwSKoLMqwKQagf/YGFNZKWaG8yCOF4Jk4htMyrvosLadZdmSUdXLLdM1ElKUCWBihPg8ccvuLMrJKqlusFkGPLLr6nUgn8tEvWaQKX8aRaoI35vNQW7mlcmWS6vmcCqg4eAQGplArE1Kr5D8kyH/ViuraonUf4gu1VjzekOCW4UkqKceuRZ8UrBMAlxwdaCu3gGjH/3F25aKqeA/1GzbOy5xPmLSv+rwsDYJY9YjTXEcwxmAWqXAOiY/XQNDNjX1zfC5JJLzVWMJUBu1nMAA6WjrIJk9jKaXX6KtRcVu0+KMJ4Pj9LVNBUrZM5Q9O03scruAJBuO/7xtd0EiUt2ngPzXO025bb13HZktWMtJt6mauNpZ/3ZnL+bLDk60vwqiGAuah3bL8PdFNrtsf4yH0r1ghfpdlvanp92+8b6o68THLnuIo54UvHuWYyn5oiYLCk7NmBnPVgEnEdftUmkkH1Ypn5g02mbC9+O15n+/taCqEkymxF2Jc1Iygm6rocckhv8F1OGlPoE3L+YTPx1YXZ73cyDotyFxBKVS4Uhf7b++9PhaDqr35qk8Y3/ScqAUfFpmylWDbFEXFRNRy6oeKDFMU+R4tt2Vi+jqnqMcHwTBpOupoFmXHV2PEodSXjSuagDkkiY4vRJ+KIYlwoDixE7CpLqA/QwwLP/JECFM99QJrSdTfn/7wBYdUKhq7k9AxkPiqnQw4UBbKFTFvPRfSz1zVtg9hCnknGJJpyz86voRZs7Z5Ncl2zH4GhTX3uxssnfGEuKycpUUm7+eWHVeFB6c+icJc73HiyocZVzHgXPg97iU3TbC9v3EwoQNwGUq4ZiwDQyCcZdqT9g+3oWliemF2HOcKNlXJjQ155fsg2Mm/UyqFuQTbNYM4KxyMosRPsSc5suwQpyaI6G59fruuds2mG7bJPOH8m5ClFXhdu/hiDL6mYEnY6583tqaq6dXzhp8XeP7v9d2oGgUb/obQHWEblqnZNu1/+5XtFKH5gg04h8YOSZUZ/YdontNVAyTzguQifAsQKhodvWwlgzAqlxJBGYT56c+k7UthMJE5uoV+T10H4Ke5vzUQX+CjtEMKH/M5RRIok0hf6/N89GOJ4FkiaUnXHJnMA68j+8XUvQpOa5o13pkHwQuufbQtsCzelamHG+krFbJ4D5Z5x2ME59dZQ4wR10ZfegmHtGLvuWigQlJ4zRsuOcyhlCpJv9tyB7dU/j1mtavgP2MR/5KVMjoQSatXWHe6r0WoSJ25wRtI2k8H3JZqIHTbO2Z8OTtmBTAEoGABPjhlWwuY6QTvr9bmlSQkFV16+kNrXpFj4a0FTumDrdrJ/3r0nFGwTHiYGKKzY/cNTFt+Gz95C/uXWrd9O1DNm6lvx8v76YDKWF7qrmOXRAJRp+EozIxBDdnCFKlssk0lipcNK0Xf9gvvnlAHqxDACxpvxsjq16fitLK7v5rxQRa5GZ1i+G0UXq+ATKazL/itnKMdpOHSHud5/HhmVnPiULEQxHGBEKEKHZLBHEO1+qvgBvTsf8OnMndZ+HrxNoMEPP1qRQbOOM2rx96VUt4hACR+llkE8ewXwWKPROru+EWhJTWpLEMdhhWU6h3mkzv4nMK5xBqt4C118MhjZpESiXsTjqqdsT5D6POuu43cfYdboNdCviP+scm3b1O4RDwrT0i6i4/yL13aUpDb/xjtFF5XIJ9puGQ5dalVXtN8vBGpRQ0uuvhVNfqKmJV1tzYiboC2gVz/X7Zy0mvLUlzaAkpnnAbbEscf6QHS4j5P5NwxwC3UVaNsNfekcrkbyVDPiB1oKtyG79zlx+02xNNVwZlSF8heQAuqESdTcqFVdydLtr4PJurfu1CfpK56+WBnAoRplmRoWhZ7w+Kua+V4wLqVoe7YFH6IUNt8lpJlHSjLG8S5tzOMejv5QwMWyZCfpsQM5+Lq8sLLCdh9DBfdmmvNMj0/2VEYrdtuGtkSCVcuVT7u4mbmKJ/a+eKdPy+z9OoqGFXpWwEUxkBPu437dHmiiYR+FNEdcxPuUY2our0VESoJwSGbiKNm5HAeWWOC3XTlEyoJlJtX8+2PO47v22KEzX+RPuwqALE/XJMxhERTAOIfMmsArKTHaDWFAPoJVD5kvGMNW0aOZ4nxaLSX+zgItvHT8nBSB0vbOPN78ZZob+zAAz5bOrch4B1tA25GgukSFNymHWhVNziOgBKptwHl0VK965LS83R4h8WYnTOlpF+sB34/D29nse3B6epj5W8VRf4KpiOmf3GQXEf6zwNkhO3WIFpemCk0lejNduC5HcBtREfaAjoDzNFl4sAJNyhzlbF9qmaS7kSSFfJFTgMX73UKzust+KYNuGAsNdlRk3DcFZoDR3WZTM5tA6xQ4t2tdaQ5dbxxxMn1LXcNsnVUh6sBKH98ej2IxIt3HU8rqTF8Bs11rkC+JSZJVdiolB7otD9NzkxcRy5BH5r+c/+DJzccYcZIQ/fql3zeNuECtCXX6zfg06cfuD00/CutzHpZEjUvf9SVEbUgJCUsSnDyotA9T5MIwtxXBAzP0XT/jtuqn78o/tlVfOh60HqEuf85udtbF5cz/Yyl2zErYUReFmkIR3zjhn4grec/ImoaW6xY54GcsQKWD5R4Ynj2rlWvwjq2e5hjYaQB1Zd7Hg5b2LE/pwYhAEl3jQMmg+XHBwUaLLI4GLBIKDzxUXTNTL8zySpv5BrdbF0HllohnvjCTRftsPuwI4EPy/dG8WUByACqf+MCyCme/qLu4WRhWKI52hcgUsxw3+WrSGVOU6SzC6ttmEgzxZNOBBR+ovIF80tIIxS1sM6qxYz55QsDEHM/pHC5Ts0Y9ne9g4sdYufiaShOI0OM1zsQCxrwIXoXCdvn8j2nlPt4SqR3sIzlDs8hIPY0dD2GimqXmULJXhwN8/KPeyOdXA8LKLMpNZhouO6DjO2tJWh+ygiNoIPRGSoK+w09iSYHywZyx8A9HeNI+2Xa8mJpSTvXonRFgtWmMJTZeKYaQZMqCdO05WvzUzEAHTnzMzerVNuoUsvW/pSdkNcEa8txGmp+hZwFNHbqoLxmeldAmNiNTWIHEiqgWRvrFhXQnk1139clEAZ1SMaoXFWavNlb9qNvx/57mBmiIstUlK5KQ8ArpNOZ4Jt2n0FF5xytCzI3JybRA/25SSTG2MHQx1qmZAa71G/A+NwstXAgYC2z6CzDinb/89i6gf9ywC8VxIT24x/l2i27X76Tzr8kyIh8BSilOJgY0tjaT1vAj9KJ9YKliQ9XTVnDyQXwctMjpvklmcPbSpFh3OjIqiZg3mRQhVzP+sjPJY1G6p4MyMsq/Wo83n27or9zQcqcDSzjjqIL0uwX3+v0xoCJakZgEObB/3iw+zUJ+YHr64/W/H5d5VJvAyYRD61D2yYqVptzu+w/KwrM5XZfjbXzbl/VpCPuxMnzP3F23vCpG3hj9RsIfMEfeAAFZRoUmFbEaKQPMpKK0bKaJLnRhJxV/qtTfZSGTTG3AnSAmIs0asPTGnLxCJqGDBYuWoT5FSt74DWgTWXKBfReyVWOF+L9lb6b8fXsoXZ/fLWZNF+jr8frIgwMLqQoJm2vfJ9CPF2cONTXin2xWIIy4aONwWNgqeX6K9QYx6KzoFG832H/USKTPtcuvKY8d9vFNcWiuAwXhgX9eL0KsB/le+fAJsqCcssGyqsX6O8w6m15aksgaEmc9mI7uI3rmxHmLbdhccrp7g78yk+eXD6zj2wOQecTxLP5oSe3S8k3AeSsuVhZu3jmgti+GW3YTyYNxFixmGLmChrT7nOfSxVCHJVudWlP2rJohf0fr99rUFQLksyqGtjcK8RuoP7AFYswP3gaWRyqSA/bXAuZNZD9GKrbQSl/+AfcGAopd5aYtmbzvloxoHB8IztC1e9eb0n4tokedub6sdsY+mJkRPOQh32rftToBw2SfHUL4gX26bnkd/Wx8DSGGDFyKgOVAtwT6OPxtMfYTxQq/sFlGREXrBppLOpvA6mGat1f3sBODcvBL9gXxSLT5vVTLdlPxfZPem+vutVdSfvsterFMUa6kapnqgbEBjF6MZzyhv9Ju2WVCGkFzWVgXiaU2unfIC/oiCnbGZ/b6KGLVMBCyFTdkNaxmGs9vUS8JqTtexjVGSPrd8pglGXiwNXccHBrUIgPzLZoam5tcsAC1KqJ08rsXbRGQ87uULaRT0hUVD5e+QQUm4gKqWHu9yK6A6Pf4D9sIIMDAXQm3VD6RT6cnmz0QiBBJezc67ccIcL8bW/tAHHxzD/c4Uohtb2c2od0hGyVGHP2zLvT7JrzMy5tD6jaUr8P2V1vIpGKcyhOhCrNqt9CuWYGttIJOphrqrruz1wunYL1vKV9LncxJ/fMTw8df4HBJWqQq0dgfPGoDJ82KEcuZgsyR4SmwoadBH1braitFg+fihUdoLnNLx83uQ/eszoMhU3q/85QyZpoKoaU8j7rORb54w0cVRh6syVLZLNriwzXtpBN4MCmnixRhAUQxV1iqoMJ83mi/OwMH+yMWaobjDFBQQo+v6bd6R8TEOhw8KA4yNyOuN0gxdIr+jKF6nDBrJszB9UK1iUcjY6LbXgNyvDXrZnb0g30vt2bXnRzTWNjBzqesRvt9ZYlM/MLEq6ncgXLVf5/jXD9KQDa+ahrSpOWQWSGATGyfusN+0t25D65pUj1/U+Q+P8Y3KRLKL9TW39t9mX+cKZVxjkzQOxJckZw+/BlL/SBrh6h0dz8wVzuFJIqwpkjaSpxvnIA6yKFoAthQFjs98wSXpTwFQP/ZtU3cmDOGHIEa9PhiHHl6euG7I3iZLBV4jiwiGTgYL4y0f0cpVcEXIGWf7BZLu+IK0m/aJ1HaNt2iRXcrYi9vwL9WwUc6p7zTpW9G9DlVQhkKqM0HC96Pw0thNOXZ/1/e60tu/9VwVY/6SlQpnB5gl1nHfB0eTkEbq6LRTRQbPx0rJA28GzxJJAzbfu81awtmqjQ3xxC/fv1UmgM/wu8+1avBMHpYuLWNECg/M8VitMf3o8ML7I4R+vS6GzXRkSEztfDUtJnvQs3AzxdUoQy0oiUDJTB5z4Y89GpXGoamuJo5T2+beREWjHCVvpmzTAd0JW9AlHIXSpopl+Qvgs8usu+OeCOA0jN8u6mvCG5c1NDB48JIzhhKbMpjCELhDaBbkmqSkzk1wRotmGyxunxI2EXKnFkcTWRPn7KsiYJo2bkTNvYMkP93hh42099VmSV+0I06UVH4pz8V5VgDr1bV96dFKBrk6uv7ImXoZGx9Ip6FLW2k45PYCYEGr7nltYVZeQY4xwWHIyup+y+uZQaFXj5DOVEB/xUG0+blDpuht0wkfsQJmp62tilI1DXjWv5kBBfNizCnWzekwrAYBS1uWxMTdhCXKlyK9NSNDUjvIONmTTZ1GIVWTz1EpFmFDurlYCQaBpKJ1Thx4irfFWl9zjmvag58mnvffDA0SDZTFEzQ0WF9YW9zfCqAAlTotiagCmnsqWwn5+mMT5osecrl4KnYZEX+bTzapwVYwJdYcp3JmysQzCOcHDAejb5ICLEOTP8xF5j2cDegC/SDXcwmCy/ZoAIF73U47/M3fG8x3iWyckyv6h2JYZbU1gkvHzvSZvIJeIfWusuM04ihzPwgyZ9i7JDeSrY8ivwo9Dl1+w283xaUZJU4RzGgbm7DDfLa5OhVPxp3G0NVk1uzFlDPOyibMawpIFgUCN085jDHuT79Ir1EcD2Ll3mgiQK4JML737kvr4FBFfMMtJyN+eWE56I4Y9m641Vqe2axt7rUXUukxQv5LTLf/bvmJq/U/68hLCSAbQw1+jgcdoteeFnkSfEFGC+d/1g8B+PYLPLYSDZsW9/PxWxsTiyZ4JrT5+oEsa0Sq423CT+HIFgKLh9MROIPAKS4zNC4mbmDhQbcE0xhw71vob2XXbgzDO1ybmIo0m/IOpb8rxZG8yamcDvFH4cR3RsbJSbs6vGf2+2ZnrqPjCj37ikj5y4PWZ3CPL8/Kf4Mdf5aA+EizxZM5pG+PNekATrPZW87tMYq1k/rIR2Tc/CbIcTiI4b1/Xnyk+0gptmgbxrvOjcRibps3jOmNvyl6FCmFfyHMeeHDaBYS4N3wa6bNnMxuoMnTz+Bzc5wo3341VIAMtGh1uTD7SvN7ZAqLa+CPB/utaUGeMscGqjfLsghi1TmMsi+qG2KEQPAHx8i89ZvsUHeKgWLgjq05dPwtgkF5hfd2sapGzuF7ZvpKvCiuq0k4vZSjOKVeL9AIP66SiEDHzYl153Vg/suveLGbS8XkeT+BYM8nM+4Kj9yqoWCbjGGAJbBxCCP40WVVzNyUyvtObF18GcKVcuRXxocLI5T/vfB9WI44BC3iFKptvt3BXJlOQYZidIyOT5KB3BmhY/tW24LEN+JkqVaDwtghql3HgnOEWD3yNX6U1ATYqWIEIbmMNH1xDKcRa15qMqyvRI04fWuLqIyFl30Yaqfp+hmng90baAJp8RvhE5H1mU3Sj7An2kl9/+Mb5fZzjEO3PDpSl4GsV5Rm9iZQe8gAvpdD+ko9TwOjjolpuolrjKU86qULZsmSq937NHrRxcM15A7ueq21bKPJtwMik1f6C6zxOBRcuHmE2J5MnnVDxi5RdXFRk2RLIxRO3/lP1nJsaAqzSNFVi2e9gh3MvgbOFUqWYNwQyqhseUr3sOpff5LiIKivP43KmmkVQxY1KtxBJa+12woB1dTzVT3zhcnRM+mm/Brre3a3lfxwWRso0A5purjPppX9MRYGe5OQgul/1EPkr7ma1cT+myPiWWfm9bkQspXZHjlmfh6f83vIRGavZda8CqW7PYK7o9+huWORmUEQTv3YbXdqAbUzpa5qGNqyXsSfoRN3xqBPvqClXxIamN1X8L4C/TXtOmB+k4UaHyyOmJ58Z73uwmVIyHlQznkYU+bst0Pt1ltPA0YEhPXXTBGYnRB46fZZqZRhm4V+pX0f7WEggcAYy3Gu/7CZKEtVIuXjZ367pQXU9oyLeUNcaIhcF+oRABFqqZuEAijMbaN8xVuJiUI3S2h/Z0BCZc8Zm8Yo3IB1liBj8w5QUVuwpBtack3jHdqiyu/J71Zo6nC1jzBEP34SoaKQbP4zpnZWeLKWEjzSkSLYubZnWAO5Om9XJSjXaBqgNIoygj++QFdGbl7QJ4j/Ba7FLcwzl0ikmAT9DknBxVoF5q/sicK5HszX/OXhZX8CCnLQVC/NBAty9zT5ARyccoEiRZCEOLpIcQrqdaQxL8DVccJY73VjC19gNG0QdcwvHjaNi6EpxmPEILyiKLgwU2Zfa263PDRDKaIBz9u0bXbOJWd8NGoHEGPgJV3mcKq3ik9hV71F/UL/qtFUZFQjSgx3MczX3OKoxfR7VcpUMyQ1LsnQGQ0WD6nD/RId3peka5iS+/GCZVljlnvXoNk482Lp176PjbJP5K/ySv43zqsdsGTmIq0z3PtMiU6DfRCLFrfR7SxpG+YDItmlRk6TuSv5Qj3cLFk/GHxA6XvzS36uEvxYVr1w8EKQXymCCfzovQH/e5+HG4zPLiEi5DaTN893LriM1xrAopo1AFmOyrovHQfqiYvT6er/LlbWRBZpM/DbKEGCE8PN2wPe4PLcfsRElHaoh+WthA9LrCoYVy4zlITQpsPDk/4KhWi4E7lJXI+3wZI6Bam9/G+ThppB/6SqJRwAB8C0KKa/x2JDC5unPTSPqKXrJy7BE2QGTExk0dqum8xoa6xmXuQc5yxaNlHmFAj1dSe8nH8x+Z5psWPtTctbvlc2C5M98O98vFRIPUiCWhaSStpVXvi5cbfeNkLRxQUczAg29QoXkMXR7bR7fTLZJwR6XKkUngEN3chuhrdKmOcjidsXduxW76ZiHlC5m4KCiCVuNMnK/TzgkKR/LIOHnOwuJCVQ/mXG8hwgYK43lpstyj5F0lpLPAvdmlhDHsjrJFblJ4Y0g0noKpF5wHMlJJCb9Bd1BBI0zKFmA6+iGYqG2sjL157HloUTU0VzLI4b3o6Sxo9XeePfB0n8jrESTNHNQ+GoJZI0khpxN+lMaZAuwGDHMmLmX75DeZ5YEaiEecFdtEd/fxX0aSdtw9s/57gaCg+hu4HSiJpuePXJD0te33Lzux9ZkxkHeYy+XkYOC23dyESLEdZk9xQamPyDXEyHA+WUH/ZMS/x8ZaCa7G9hIuRoubXrjbNtK0Sk9sR5wpJdCgMGwUXuK1fQQMKvkQQzce1VS3wtddV26VRaDK8R22x7LDVDJo0k/PQr378EHtGglP8tGpHqnqwXSupKJmFhz3M1fnkGxYQUhST6lKUytfWoZ4WqGffQpcpQl8svHVuSFLHu1LebQ2EgMrZ1DWWrYjZn7PoeGjpINeriHz+Au+W1Ty2uhxkFAI5NCsUfpPCfptSUNmdhh21p3PrKNBL23W0Zou6/47ZjHqv54R3clpaz4Gs9YnKwlLQ1k4O0b17KdrMUiGiRhoavuQM+lQZazdYSoLa2iUbhIYhjaqFSiFQEFVf1JwupzsoqTYWny4BxV/nUF+uW4OAr+C2Vv0tWr6GaDbhuPjioX/kJ8kHI75DuXJFNV6PXTw4apbs7V3wCdigmQ4NMLufgzyJ3Qvz/2eMkG2UI+sr8WwJNrinGV0jsp8H6kFLv0gxmwN3GdQLJUNhs+StTUgVx8T+MUNz2yvSKKgh4WEnLwQGrFNC2ybNNEDtqQ2aWarUDkPa0mkPhkY0diJ/hWhp+HdhWbWXH5ofLRJh4D5490/y0GIMKnZGWeEZSptWrrZsZRjfZQaSx7iM9XvDIvPHg0QpkFuDC3UIa56dKUWObxZR6E8cjhxDt0ZkdUadB9j/+HdqIPM7ry6T3IcHCBjIgl0GtLQ2CYP/bePTNwt7j2wZGDpojtcD4C+kNMUToeU86KVFKlBz1Kx4zgLFzhxG/DsKU3V2bp1M9LClXapnyq44XcZyClZtngbG5hyvbw4JUMOjQal3NkRz9UEqTi3xCHF7RkLPQr4NNfMdKYgFuuWToiNQKsnPIG51nLVt4wTSPtYj+RK6vgvTDiNi6wwlVhcqtbp47BPa55mJ5p6b2BALPM45YwHwZaz79yq1bouXg8ESuEa+SKXM5UAvGW+Jiiv6BCezltnQcgd03PPvZmps5Z7SHwLlUnmpZZmYxUGRmXVrhNiadALVxdpFyKGZtcHBI03Y/2lBwR5DODKmI4u9FzVjExxOagzQ3W4KhcIQuTF26W5lRjCj80aggi1hdUllNtA3HXd4SWyL8ydrb7dkBE6j3v0EFulaOrJ8FfSuRjVVGpx4d7mOI8TVBxWiVdZsnn8ifnElTvor4EAK3pSGFmlBAV6wxE4YDOSKXVLwis4omur2Z6Ac6bH3EuYVp4wrWoG8ORyp9ytAzWD53MbCIPE9qjoeSTGzxamxzNjkapbHsQwK9xRdIjT95oM1NGiTsCtsz8HlAisMKFkh+HOMfza6u2e8tmVaoOwNcD3rgtwP/t/YyTt1kzE38XD+T73jMXb1YnX3PW0eDC5XoS1bBZ0IqkrrBS74d6iURKRVuVN06LjyFWsL76lcSHTae7UJm5XlsEnhnkyBbodlXj3Mi4Q/ESrAtAb2QXphMzdyE1w4geSilGFccK4Z1tei6fV10egvFjCAFtmmrLqny/8frRWLzYJovumK4B/4D2YXE00ZQg8TxIhqIPGBzlZ7RApOTfgjozYBKpPSBaCQqp2r+cr0v3pjEW28pniBRidX2wg51vaRZGLs1fteApnMgkCI10WpCKXXi41mzEOVCG8TAcjMQ0J8Hzwj1oFesbFIZuRd/z2l7vvGNHJ8GeAkkkyR/hXSbMLULLFZuvBkeelGd33Ixr650p+0H2KF+XtvmMK/qnnsCDX8NDjxL8i7oGAeIrx9wKGkceheGCMEGO23tda8HPVrSjiXzliHXcrKHto6qeIPH066b4czepVNpHXMugwzLyhMh9snKIQQxy3FtfsWJgje/LZGRDlFJIOP0ou3BDESWx0mLQaQ65xf4O2D7YrywsHhIvN2HRvyZc9Kiu+Bn59GH4hg9WipC9rWcGOzkKX3mAv5Z0aFc7HCLYQYsTSj4vtIVW0zo5mJJVP7fCqSzw8sIqnN0IW7DrcpdL9XRbms8AIdf6qGnC5nDP7D9RFcxzo0Y3Aaiezd/rpFgn4Jn8QHtuRjFZjluMbBgh6d4Y3m0yTiaf3Ydim6rUi/Gqo+bLMPNW7qdda5lnmhfiUM/f2laEG1SkLAVK3tN7Wcp4L36txibh8V+5sxIA/QdtI4pZxZ5HBiQMmjddvEzSNRw1kKo/tHHrGhYYKbBar00C50upBBK7dRhpM5dHo4HgFUpNBG2PJAFVotHWjuMiC0gEh0sUYvbN5nkUQQ0kgVq6JwXVaH0WxSEPgXKJKXz+Q2uN1HcJnoUQnsPKMNSV5BPL2KuHKrVCw6h2YBJ6d9Zlt2sIWC+8ubliH7pddbaODsWFmO8nWAME0ws6qjXLd1sFXVipZHk+Nkhwu3FGUeAysfLHkyItfXByY4XTzPwB/x5QlrwsJuNDHtgvk0H62DBtupjczDoWgNW6diAnrn306cfibJAtH++dfGGKMyNDJzQXeAmKTHrkzKrKQIYsPjnlSw+LHvsfTGeWdPb8DnmT82EBx8f5zcmykelCqKK4doxsWSVO6q9xQImoBq+Fie1pTy82rYbR7wTmkSIPvJo6N5FlzT7MuGIYFJPOKaxEytEe3O+bABq/SV3TL+okt4njehdpdsBDyh1fRlcRzPlpXNNeT9KE+UsorMr9bb/rWXliyj4x6NjeYl9n2cYfP2ueisvIfBZdIJHjmsy2rfjzsc/1yMWGJFnI1W7wGBthKan9CbNyR5AJG4QVwuka+ltIgbTGXm80fir5sotsyRv1cDAWos4Wc0mtcZKUblUTsTR1PTREeL7G9EERqkoC4D9PGGwdqYl3nQoSgzNt203NPUEJsbuemg/jcfqGorE0RoXObxOnYI0nDpT3FfrW4fpEYpvEM+NJktvZS1IKIZKxeQH3dLFjejYq9L3eR2pNS5Ca2ZqvoQieWtU3kAN3gaVgveNDzqBqv0KvuWIyCCIaJiAT0AHqcxR9jSzEPJUNKGneJhIEscG7TPLBVEa4nZ/naIEhscsASOihWLo1imOTedQvshyhQQXRKwonBu4usj0UeKXJX5wZJD3Tak/IQgNCTk9NLSKRVfIbIPQTD4RH+G3r2Ig6JGkNdWL9cXkd1inEGn/BNTS3xWELuL6PR5e0TzQEiJOA6XxWoeDpQpTMZRJCjri43MDPPOAmx7FU+waLF/kBvbm4TgBKxO06+t8KwxERaNkkJ3Q+BEHh2l/n5nai7Rxx2s+mqvkLwTsiOIN+jmqfy2F9U/fRJmMu+OnVL7j6EL05GKotWV3Xelx2zec//W+A1tFxb4jX4JKjVAING9dLibT67KDxoDnC4bLvdjEzw3wUnOw89Wgzmn5Rxu7Zb49Xm0IeQPikjUO9yX+lRrvwj5X6FfSEZhIX5CxyrfWSn2SkxVfI/LAYRdxgQc5YQR0siwpEpOXgS3XO4hk9H9PG7YXRk9tOp/VPMf328LkPIftwrfsPTD8O7QZ++SGktS0L4LmWqE3MKlHm/2Q0hjyuLMEvcdKDDpv2xqfiZ7t8uyRCI0a4SK9map0/TDYfWJKSxAZsWgL8dUB9jwcXj7TKhsq1q4r/NSdfvWbugARSJbmNo2sY7Q/lsyZ715l9on9h8ip18VoOq2IEiaxwJAW1qUkKCLOcmWA/NTJJl2v5IuCl4HP0I77Wya3Q3Xv3ihmud4rgkMo+KDBiBG5VuBVYPw77auxd5XZRXAonXchirdVwMRQrKwJXKjiGwlMd9eZyrehJgRKYLS78lZ3ZDUzYGm8hRyFpYRHDffKUF5rm+5Z2Eq/dP2+f+thcVNaQG5I68sWBCnxHaY50uaXTM8FZbau5/vjCTI+F8p5b/d33JusoUKLqZrzNZsahI/gTje+dmP+vCDLQ9QklaC3dGwhMnk8s618Wgr8H6Rv8A3+PoY5VmreHhwvc5qh0lxZitFLab56y44GlcKCOTmoHPjVbuFo1//FeQNJmoDGRMcXeux13hiL7iVOkXcK4Nb76E7dbMBlK4L3FJ3rIUoWbLxNbg6q+t1P4ymsEF430q9QEh9w9Nw+CGshx3A2AySTI7Drcqrxb19QXlBCgnbDCI4iWAOLdRkXEifAYiaLyL5qfQS0jP5lcVeOqsNpnNQy6a6EYk5yToUBJnOuMlCN/6DYO2SiRNTwZ3bcYUgQbQEJzZXM002BtlMjPV0XxDhGQrmviP2fkdcrJQWeffX2nr/4IcZGYz+EtRFphQ3609WihoM+8QsCL9NYD5zkUBcmnV71l6qyuptvTFP7HdjP+yMtrtYZxZ93rxv1fnkSGoTlE0tRux0xdf+THUYrCLMZtgsmhAkJ9Ry37yunIQb9fQ0cLecnTeWvfhJwDf6g/65Be4rbHUGvjEbQiqMyMSFPut//LLxJOM7gp0P6BGotfKojt98GzAY5rxwWwrdoOM7facJG12dw38uVhsgHSlufx+9Xy+00Oz0/tFJmHSoBP+QI784GUrX2tB3fCvxWlY/qhHjB/TvNtbZ9kyN+1LsU/EMlO3/1ab35W5YCKVT/7qSctq0Q5rKfEH48bvvP0Bbbs+XsxlfEEFDflDLCDKpZe4t9zNJAkFcYqjxUvtr2TT5gcFPtnQ/SIYAO4ufXViYqN2vO3V5z5hYmwSBl1MRqDA3YpiBt7iAZbGRMMX7OZXasTYo2cLX/VQMWWEmUgonDPdv7WHued0Xj88cI4heLPy8pkPkfkepjtc/YtR3ejUb9ekmXjPWjxqbV3YNaOnIo6qh5eVmYnPvwBHPKunM+uCINKcBavbIYL3sQHoEtmxG9hIIJ1Qa/5nIF2z80JcomhQnmQfSsRk4MkwY6AIRXw/Q1sws7jagGKHR11iRJzHLzPkLWnEVhLtVD+a/dc79CsBS22xSl90USRQoES3fVgShXeU8mJmXTXXuKcyhCorGRvwYL/2Htgk6juxICdQg1k7eFdQc/SSVdInfDmeNbA8zNw1MqyQ5TGSHZ5k08MjC0jmXOKgddYlCFjjorbGmZ2hBBjTavvZpN5ElROxXYkt1B4tW2UPfYgQwiMWMh0jxAqQF8VF3KjN8u560gnklF8ufEQfi+YeZZWiM5GEqjQMXfpv2q1M3m/2PgsmZX0+e7goYfeMa4YXPT3rL5jv2keKZQZSh9rU4V6zOfQCaJH23lqb+De8vM9F8vNN3xWYZSlgpnQWv3e/mhug24dfP9ON/ZZ+lAcmsZqF0dzLBoqioDHMso4t5MXRHHs80l4NoDAVP+Pti3YABZYs7fIBQf0WrREIKkM9jZYjDjygZ/hWC9UE2Q4gM9cucfDf4T4SKO8lwRcxY74v+iq/ht6/v3jFIpPbjWEsMnG2qOdLLeHlLcVeFnkcLOxnD0dUzwvWd7PLx8ICsyuJ+hytRF9wrjk1u+mK0M7afj++C7RVbevEcjBX1r/zvdTIv5xh79uwFdPBYokTfLtpk1ppNX4AqwPt+G7TcabqYbdUwONMYwqTTx4APNNH5zW1SrR5xrCvLs49st2/JUodAPdl1FHH8YAcLYIb63HJBDrYu8mWHV8YsAyDbmoDyxi4MlhGAXBR87wyOg5DVBbQmdd9zRT/1MV06C6lVZiRdz8pk3jItDFp3A19urlm5s0pKufWl3/qtVWVyM7v4wA5vsL4ZANnKhgk/K2GUE+6AyLBnmKK22nDin5rlhQ7eoLgT2kipUM7lzWCkg1MrY8GUJMVzet8NFBr6NzUyKXf/m2/WgeKf7HSWRHm2lqdvxfiXk7ItVxQu1EnDpYqb79f5cL2VCtk0wSZAtQgSemwEZ9QjIZgjucEd5/CNlATPL27TrUjWn6TLZksbkJtVZOYmAWdD0XOl+qZtLJKsPXxiiGtarJmnGf9CK8OPt502+dbsE0OyzZz68nlg+FYhcMcl8nfeMiuTlF4/XYj8VY3WkDW0FoXHa1uWDsG/hejJ15fl9K8kOuSB66k6ji7oM2ahd2sn3GNKgB61eI4iLM9ORVYwzGLTig9Ryb2TmNoxQR47AdeJXAHXhw0mT3rX2yaRFn73bzQcRYKBTl1yEBe4F+cc1ZZN2C0axEO1wkfNPfD+FyrxptvgeZd4s6waLonu21wUCWMumuFP9EsixevVLwZWx23Nstw7usC0kDuMNVSrCqHniFQx2ualjrB4Raq+5VHLzPn2/BCmzjrGXxWJGkqJ68gLFcHp1v/Yr9RkOdF9CuLWX9Um72uJQ9WCcr433DThlcm5YygXxSmrwCxRfXp44AMxeo1DlCSJlg9eZeBE+qJQdH0c8pMhPTebkW8ji0Ni2N4eLu77m/P6+A+yD7ysN+l+B8DdzZrqo2WW/0Lk2B4x908TEpezbwBFghxcMMwTaXutMCYDOL3/5OsCaW1Wk0xF+k6oj1M/bqrvM5Kb846tC7qY2R9qp4mFmD0GSWXw9RJbrYBN8vW/bvwiIxCnKW0TKZorvfoJIQ7H0O2uQQmvy0eIq6Yf9DmR87DdTZKJRscjsxCm90d3s3SUrrRaAzzvWX6FH+Z2A7Wd+YKeW/fVHd/J6SwOQIDoUPG7YyYovST0O5NF/tF0O004+i+e//hV+q4u3xdnTHH4IikxJAbMtjAoFMnJ1t/8/KS+8tfpWz74R0hW23sb3Gp3FnkSk6JGxbuCZCVaSqyDrzEq33EENG4Mrs/UFWVdm5/ajxeRhjnLYNTO+7OYuSF6m3Rbp47GojqCdBVTxNk+bRVf4mCfbnn6Icq7pzV8UN1MFhf8qdSRUxZk7bFsCwnFrdXC+Ssk+jfCg1VhzMC7xMf0G8tdLf/r/N73iV0tWvm1E8U13RQZaRkx1kgmJKNSHQIJfb7ZfqYOBBvTk1FOBVI3BKiciLN1Ex2EcuoNYuikTqoEMLwKR0jMk/e5L3N2d0zUvlmkhOqR2MwvbWxOdHTOWJh/SmrUZyp2kEF4DoTTV52FkPPslogqR2g7LOkwHzjOteT86OND3J23bQF3EnsK6WyrXwmwBBBGy8e8+YHBeNJFvmnetkWDLOGbApcvlsPL4X3uU7TFuRNeh0PBlrCdpCZojCkYLEGPnls8nSkrJwBc36gydx7rs9bwCNO9wQWBUsILKUSFeyOGWlx0A6JBM0Gaca6YBp1WtC4raVNRXhYAlFRFiDAH0S0ZmiWRkcVcaCiapZAm7KwDMevmqKgMAGolQnApirm1sPtAqUIWuYNppK8I6ByIcpjgUVnmc1uVXsDi10Lo+VlPyFGUtNdIvrpyzW1VK5iy/xUX3kHzjurzK0if3O7AoW73i/gvQZLEC7vWa6tDuwN3kaXINNJhsVoQmzbtESOHXGR+pOQ6kYEixXMbLDX/9HK2riSMzgrcYB+0zSIKbPdO+wDEficWNMlrsfYKTkLrSrgQPG7/qdTZUU3SHy4/ZFRx/4HOcKQX2H/Oq2e5P8x/MYcssTe5S1f/mzvBcov9TNAfYs2/273FgXh6d4M0eCcZI8DaIUTrloJp7EQBXzeTv2ef7/Vf9C9N8ja1uHAHOicp+3QpwBVGt10RHcAHu1sQCCAXDDjjBfjVorLrtUE2O/tKDtGVrkYArAE7NguQS3qsH+Us0tDAufafOcK3BgUaFZisAsPvXxcEAMAeml+eRMOvWNb3mPPPwq2stKNydmOmnrhgHVHLUvFa7rfl2yO0RYqUQv1vajmv1fTE9ySiMrxRka//cpcQZQCxO6mtHuvvqVnYGQyFoeOPT9v1RMXA7ANMcL7UPqvDVOPyTvSXlPNXPZgoOEEDtbswDY7DTiFjHHi/C77X8Iuc2ptjT9DpWu+jqfG9KaCmc9b531OBFEHsBtSqMDo5t6Gz52RLAmOHE2v/ovVbD1YRVSx153qd4a3skhvfhhXP4Ra3AroITugsXPJ43QxcnGX6rCjjUUBGFoqjN1benomVvz/2eYbAqbQTD8BkgfK1EoGsHbHCI0Bm2zGHp2JOmz9Y3Vncw2W46HgcuKj5ED/3yd7uGcP4ab/FVC8vtwkz/QsWADCMCQNb4X7mIGP1FfDadAGyL9inz1p2IsTyVncF+/O7h8v7AsKj+8jslBpGk+kVWzHoV/Gl6j6Mt3lGGjw39NQbxxlpW3gALic/KemEH8M/wvadGFxd13VlkXz291s8Z37FMCJS/3czVapoge1XW3soYmPt1PLt/lh1KyQp7Vl3MAwdSSI4ED3ZEBIwa70BeUsx64jumD9i04g2o/Ez+0/a1gQgRR4DfxLY7/ncQqyLYvwK1lFa6SbLiN8ldugPvEgqhB93Baap3pWXcDNQtUQNalico8iEWCE3q/uHFUMrYOTKS1xQIIcEuVxwB92KfS6q7ewAkv2WAD48ZEIiAt9FUlex2sqqDuQUk9JefyxXkWAWdPSLNr0vI5RMZrJOWR4nvEPchr8k/O/iblSzxb2KO5JubkBs9ubAx+1MBkDwQ43w7bj9NBN+N0MO6s059l1ZvwqkO8yFC/b6VSU0se64qAs0FLLMo0Y8k5ocbIs28LP/rkhaQyIzgJx7CLABBlgkeOEEDEOCbw9R3HYo22DXvc4U67Vl0dXpzmLe0r0JEi1rqA4567JEtSEsozxaIvieGp889jV+Uo/PQdOxQ+ENIYGA6RibT/UmxdAG2rp3Xk82ensLdWoSp9DXT18XU84wThKnyr3Y2ROoh3zUBmRUo24cyKixh6Kne1a3oq0XRU+iVaaN8muazAxcPpUM26OX7N+8vZoj1gEnx6IqOhZDQFLvvTsHe4OkqdZCJAdUBkc+mRQHUVcTVKPrlbDSg4dNixkOQEU/jF8c3EO3yoKeNQW8uAMRCV0LXh2BVoV8tIyIb27mCi73hXell+gwRkuMa3RUvbaF7ucO0J77CP0eSv7tCPQ7CnGHDwBMkGICfc3CPHE9u0QIuf2v+ueSOTdJlLsPEzlk8mmsSLrf2iJREDkedQ+Tl/MyOFjrmawFyNQGolFpGylwvgwV1kxeBrAfS609OIwKrbswOsfC5kKsp1ILsglfyqRhdEiGegEHR54DMzk1V93+/rLRgz/MD9dD0oV9WwgCfaB7hasFOEi545IEdw1lnT1bXS7b+hW/1MUiK2LISTk7dgGoIc2JK80xfj2O58haZIKhG903FrTzckb0EhBlwo8odK1KEO5lhNZqimsDxs/ChmXN+H8AIwLarOLkYE/f1T7vin/QxBwOemFQvaaDGhRJG+aZ6u2E5rTF2GFTOMm17TFs4hMBAApr2dFHL8vAH+DYXCPQd6oVdGTSa2OUYMa390Gz5jlajDPaXKV4xijHIhSBRAiEIuB0LcWk3NYUG3gyeZkgDNmuShNIIDfqjZlwHvaB3HqJLTFDmHNg8DOzaf5i2bUZVfVTIrGuX6r9f4tzXxOUFw8a4sM5NKYbZi9JHMLDdGz47UbIfB4Ce4Ks8xeyibfB+nKAdT1pWWgTrpC1Etjiufs8DNw8U65/VpXHeNdOprVA+6UTVgzwj6ZBeHhr8/F5mk2GMiIBd0F0gGoWFBOuIvjeCMPnPLMBVA1FQANYQlJZDO8iyIyhHWBLgxPNsO2Wm6dRbpcGUySYpBDSOVaPx9YP5egYKU6EO8ZIrUkamibcOkMv1NmQ7r5HI2qfN8TNhZnLdCFUxMEicVi2CgcDnKW67b5fkTxn0wpQgcP+uWMY6B7uSnI5XUmOjiyOd53DBHIeEmllM2apcp5JDOTfMjzH5y3o2cDqSetPVud98GeSY7mcVJvgt0be4Hi+FJ0VFDRuR0ylrBS0o+3IynxiQNLLV6ggEwyke95WQe0pQrxM7Y0Zky5j/v6csrP3/2I8szYPxLNKtKSboAcTMGcC88hNM7ZZkSIAjR2/af1vjGpWPW7XUaX8RJivpXxsVPqSYwIfGnGw5CbTpsCVBIivLJr4TzkAanYowV1vgHyEmJHmfnRy67muH4JYEcGgn3uN4CBRy/EweOFU+NtO9BFbyw6uZdzQAbMT3kzfvUXYAdGZSrHuA4tN1u5Jxp23zXwTZ1WvJa3ZYRwqrVpkH2NvCckDlO5pWe96WP9cYoBkAt+CrF73rGE3uk08I8cafSN8ELHMfehfR0v0ZMvaskNIomIJeFxez9J5f1gv0j9p9NU6g0UT6qP/bfR6z+kW9exRrymqGoDd0lsoH38phKPF44NW497DIxbfbTEJYEVwlRdUN07PZIvQRELZVopfBiUYNvb99CrNJVVPERNYfpqsU7NrmHbI8HbawL9DI1o0c69KZQlDPOcYbhp9WuKZTWVLMmxJq4q5nW+pHLdFqIkOWtqU37WUUAdlf0EIylLfWd2XZTWUlUitORnmGigh/CILV9g9nKMZwTwyz0HB++t5/x4Dqf8RL1Hr8KNOGtMSDd+Z/N8SwgV/6Ucp47Pd1i+W6D0WtLWoFHbSS7KqI9xiGJ/C1+ia52hZ+63v+vqWFdCyIe6jmbZgBaoz5roHNjxb6sDvMu1rc+6tCm+dx84krPGlP71KkO/xFnCkkeLwPMYLRXmTJmriXe15AxhlGKsZRTx2fp8w5wyhqjypnouYwgIDEeBPmGbrp+augb4k4kcKKCVD0zw9/AEZVhHf1TD+xyDgXsv+yWxUgujrdi0kkzFf0F1xOjCCM/ZX+JQX6XHeY98DybfZQWLTdp5SNHTYS66f87n4c66dDT48NgZ2OTBp/8NMXhSCV2vhbr2w5ALyVJbCw7eCWd1Krd5t3pLJ6gqn+hGUWRGulYYYHAHWMOF0Vq5Ez3KiiDj3hoh/2GhcMzsXu2KVwZP6dmuHrJoYBJLbVgWZH5ZPf/zjYPLqPf5HYio97CgxxEqC9r58aLJUnqFsLrXzdtFcUqZXNrQr4CAx0jtR5ZSW3n9lu+lEjtV4A/qCxFarhkY5Jd1DLxjOMnxdZ7/D1c8mv+jbwtYvfAX5GE1nU72Vf0G/JMolEz/PNI0UqqKx88HK9eebNDzSQ0l6VcZgbKTCeFaBH3jQ/XG3I3fLJyKWERCbt/saZp9KLz+R5L7mJVuxBEB+3I08DsOIqGezH6eUsSy+0to98wjtLw9wXAd3nut9/CBdHoCawxD2miC3nbK5dlb8TV9RzCWyihKkLoqcFKshRkX0Ch3Q6S8P/jmbM12MGX2+Ul3Wbgk8Hj79BBawbHlpAGjxngyb6RYfZKn373LB3OF9BNOD4HCTxQr+338m+IyO87YJB51Gucg8fJflRbcUVrOT4ryxK2uXdJTp6LtEbhCk+UyoBs4xmRZbzK0qS6A9NEXrChRgO+fG2xf4vobZj7WXH232hBvtoo+TUnwazj28A1CFsUvbcmv5dt+zURpYBfuwtSfEaR9gqt0gnfqA3k06teaLlIM82sf11Qy6aKQrziG4sWgWPTACHSBVoPMT1jDirINTn1MfpJ4/NyxHCJvSFkuNUkr5A5l0mPonGyYR6qnOB+G+y64AxmcT26uvN7Jipa3KpO3rJuER8c4tjDa734Mm+qFhPhlqmMmPon7l5guamsFkq+esMFAR+3IzeF/XZCC9gHhSc0g0pqF8zPV5tK9xqh6C2pcSO8Gxxj+v37KnXTv+dkzKjg0SybsVS7aBAv/ZMJjgUSNtoqxk4ZInMpZp7DLPToWkvS8IZxgMI71AUITVDHfY6IslcN6Chv1YHdnO0e630qT5Z2EtuGFf21WysDWXBtZSpVW0l9X6IRKQ6no+LLMtphJzvvhuQGozp5a5YEDTaP2w6EqAaou478TxCgJL48uCzKLIyyE/vbr75oDu6LFw/3AIvLEjk9c5Ykas8a81v0K4kRSiDUlX5szSp9BbmbwRvYBJZOjG/P68JGhum0F3pH5dkWYnNK0M8ulAM/1cAcykLbvllLITsbjIjf0JqBREzJVb2DTWu/w0jAETYOXveouaeN6T3ujrj9yWiqEdabIRbOSqtxVf7EAMBXtf35y1bnFWgsbY76Dz3E5llxeBLHMpbTZeeBaLNLGCd1IkT+cq1efVZeNFIJ3jtCsFebA24LZcky3HGLrP6j/YHAw/VxDnRlIrUzAD9vUOO3eRvdeYPGkik1Jc2obZ7/wHi8fATgqvsvQZltUHiMgbN993OO71/UhYk/6IDmkd1RbbVC4xstlHwPRD9ayy2X6ozmJ0/8xjg0uTqXCDUWkTQP+X3vt59EvOpI55BDp2q74HJyuo9dpE84coDPh9UjHiAcz981eE3WkqCX8EKQr2m9YcHb69VChf0T+Q9B4ppvNhpV10nrdga3VGZa11h7AXHv7cpT4mQkMjPgZE7OQQuc3X5uaShhyYBNznrkILh2ZChCUKMmho7IbWmVaiS4sO+Mxxlh19x8iJ1T+X88GZVWLbng0O4wKyVDoDF7dSncAK4mR73Ly/9FLWem0KqyARm+NbPLQnTepsslze2vixWmbLB+v+FfH7ZQkqT7tnMVV0olt/wQ58OjlAKJSjW8RV/KCW68UyJdTAxbChmCc0U9xq0Hx7NXLtk6re544Qbsz45ck3nybOF4FMAlA66L7Oog11ykxeGTqgKWsIaoGkHuh+Ze+KzU9ILS8SLzzr5LgQSPWtEwBqqvElWJY7ADWLaV2JRaJODSndixyGBzv9QiWgOZZaSb7V1vKkJd/h0vEUllNai5cIDkG+fLmqk5+GmZD4nlCKoUI+ynrCBljRK7kCaclUA4mUuAcaaN3JXjPM5Vsat7pcwnwGbPO7yay1WZm/qWMNcWtERNC4g8bC3dEpTCNavmOvqNL2symcwWBEecNiZejaYBF9yNSxFht6MzC5/LOhmf1Kv0M562O+xC5WEdL2yE5bjoEdRNYuIDdDlz2GzB5ZGELf5nFpkAurhh273arATn6Y2f2Jal9Kkn/XjWOittkmD2UZg7mAb6QYEiatZFieWaDW/ldVtUqud/R8V/BBAH2Ai9BT0tXiosuDQ2u/kCPqwInfZg+ugz6qocX037ucV5cZHixJdtWO0xBHcj2rxPqum7U1b/kFnds8vjlZTdjwKyEuPv94pHhjGVR46hhflS96SYKGdgYoIszjIkP2bCgysg3etqFXmUDzr4kd5ONo8gQg79P9vzFpXFQqN4t5IOZsg5bZ7bcbUV1/dsSGxYmsuaFl0I15Us3TNUM9sInaiLlylicsSGfc8qJD15RCOuNtqMHitZaCQRcgYmA+GFXAK8KXFRGt9g4emsGVKtSC3N2nODJb97OluSmnkLl6sGRn8Qmk73WFBPZyPKGXewA3ov+1pS9YqEZQp9E0MqQLtdb87WJTGAJmm5plVxK5nf/eKURnd5589aKVkyfeCFGvajDee7rQQGnuVWhoe7ga+A7hh0/TQumj1sP1Zjjevbkc3PbrFB4L5ghCbJzRO+1hnathlV/gcOPshztnxHaYGGlKYF2P1Xt4VBtVNfcnVN4dIM926154teI/8LEnUBqqf3IEJZHbEnH82WGipsDXVBP8oKQkbDirfqW0KDuvzSrkdkuaSO1LtTNAoxzAQJeQQXKns9CAfuDLlSVbRJH3mPDBTTjPBHJrH6wdwYp3y5ZDmPlvnnI651CA1lg+v+d7AmulkV8QYSZkOsdtuZu/grVUL6zJ7dJpOSn5I7Gn2CqPaHisEZmyi8d0Lgh6DeDbqjrdNg/REhlNrKzEH+iRwcUVN/JwnNbM8fFTuk5yWrKMGh+MeJBOFyWtp7x6XiP/SbHb/HuUkU3UH5DrosQrSYtS0ywSXlGPjQ3on6bTG40VSGPg7cRu2xbrxYMf+IuZ2wW6I0vvswzPKsoxg49J7vXq49Uo+JVpu2HQy/G3nMr8H/q93Hz51ThjvmveKAi/235XuLMeBLhHgL7Kn/WVUrASq9xSIP54u47OyRXMB1eFisqFvwP9ILGFCgJB407DpCJ8Fx8sdNA/HLJ865mlW1Z6oUdGbSPy4LGEgWdBBua4gBZlauMLkdNdaDYl8PiygIVJVa1op28Y3onZR4C2OV0Ag2qX/IrgCmv3NZ2PpbdqLQLwTKnsQp13uyR+QikNjY9qI7FPJ2mvxozHiYgxCc7wOZFEk1UrjwIwZqZYYdAjI6UrBpu7clI0076Cg2qe2YE46gadSWS/2pvIvqH3aBe8fscWwVgUzI10WAVhT98/GvE9BxUFS/JIfhuolNRHtz1AM/7nSRYnJVtYP2iqxkxvu+GPFlTAaUASa9E7HWlW1ERcVtIEdkkeDO61pfyzu3bMfe8Gmsd6uwt2ubc97/3kzDtQPmGjAXCpL2tcvFyrTdLEjqlstj+8Bn5B/9aLgGi9QDtnmpKBqgN/defLY7Rgj0ZfVJmF8l2GX6LMLu0zyHPo1BHL0+OFJnHqkKtZct4jI/1QDh9GENr9J+5aSuZNCQ0ex0OV2Taw3yjlabF5zl54TcrGAYMsft09Rmrqk2d9DAJHXITKv1IBcM0mv0Fmd3Kft12RavqFQOvA2BquqQ/KTIAHFfqmEjWamM0sCUqkExBcgto8Wdzf91h1etHQEBPE5DD5pryvcb0HNSsY8qEKGen/PqyI9HvEBOhqSnIl24Q3QuwQsfkQ+QGWus4WAe94E+TfCJenRqrlkxhQh17dNomjT908X2WueAvLW3VirForgXab0ZsW0FZX7c4g/4NLOfcw4TPn52PWGh+jH7N0zU8qygMgiqjZGxMD+XwvcUMc7BDtPtxmCrRFXLErss+V1wkCj26llRiw+DhQGxfIETXEdInF998yuZNl8bC7lwDuSnW4BAyW6cO5RdF1zW1DLNsQl+uGTro6oGQTxr6ua9OVjpLdOC+JwupBpa+pG3UYmxan5Y60F6yxqGk3iZm84agoOYaD4dutUG3Q9OIcRTTk87hzx9LdgFdr9R9Rjfj50t7QvUSWm4ZD42fPh/J60gerd5vDWTHq8+QMvIVwZ/lyPb7JdlqEaLClmIpnK+tVQ2DLv9NOov+VwOADI3gT8QaN+BZWiFiLd9HscDMUcE3CUD5ohAl86UG42lEeKA/9t4cQqs0RoWbqTJLxJ70C2TK3Pj8deQgR9oda3NEaIuI899vrSMlxDspedabhOm+KqgOOzlov9A0A37OCklp+38+VIIb3MwUtA3ZDaUbf7L2e8WcciAm2iGV71tUIOlbHfKkzgLk/GCpruoMYBwhPn3f+6KCLWk3D/jjEsO6B3WZdLBlLyphUJklLT5o+3+YBxsF3E7aG8PruldgFaEmGTqdL5vL8A56/QzmXx47i58C8kXURWBikRsutxIj5hCK2XWgT+N+xLn0HpJo3CMRNZx7MuWFgEe6yKvmZ/qxjfrnGKm280Bdf8HXXjNIMS6ajDcf1ubH0V33Ah2mXYG/FDY4zGlavVBH75YcQJ37/c5i+63sKZCLzjRSZyRmS4dufuEs4bWdVsIPkILFkDg8mz2bGCMOnuPSHBZVTxIt2YZ2oJjQryMPqSuIVfv/nHF7VrHi5LGWXtFPe+Es6pCDuD2DUeOJ2brg+jsiM30r1I2sIamSHcOaUoglJd37DPi93QSfGtreA+YOsDiJp1rVw3dAa0CW0WOXxSASkcU41uhZEfpYOdUbSJej/2InYfv0dW74zXWcvWsMiSbDEfzHjPtbaXgG322orR0OUMHMIwrkMDgkwp2SWk1RVS3OJc79ezBnEqWcA8fYBNOSq9e1HIC4KFlu6iv+7zMApyIXxpCiJrjhignzWU/2z1PV21CTqL6gp9Nxkl5WZHITyh/sAMbogVcYOm19IW12FtJ51xhHFiwOmqebMlMwojz8I51EnN5JJ6gvYxRKbNpPVfxWMLVY8J0OPdsQBhq3BdJugP6Rlau2Kh6StR3gJh/5TZ23Rb4VfnPEfveQIRavXOYF9699yPJehQrfQh1A9slEdKXij+DI4+5g6GwadicPL2Ti8C0iaPc452je8IUsxzQFvljrshI8Jk/6/PPM/7G6go7LwlBMAWYHWMdzmMcw5RO43jWPHkrqj8HwN4ENIn2yg42GI/ay17+Q+Pm7cMc2GfeLHTvCsmV2f1ptLQziuHLE+mm1idpNAqOyPDWtMMMbqBY+daDE+VvnVyqLhpLA6WS80z5FsJEhk2AaXYxa2gzi3V3EMpOCFSOzCvPJPbltbtjt1NoglQ70EleeA5HtrJV5slY0/PaFJBho3kUTnFe3fbspwPfFXgXV51r9JE8y021cKV8Tl0vejdlPlaAagmaPwNz1wT5jRVXci77FjsxjSoW8JuS+horXNdl/2X7Gd7Srk4ubp8YKCZe0Z0Y/ChBWrIs9JBbCkh7K2KV4+YKn/+kNYA4jBaogstE0YmX2QUUJ9FM0t9si+1SEBefNzNiaI3HQkhavlcv7sZQCgs5pue5wmZLj4r2W+1r2CvY6dkAKiVMqS5MGeawoK7BpPf7C+K0wE+yyceQffPCggPbVM91ZW6s5J+aw02AFAGM8d3SoYMPWnwz7/eTYS+gaHPQC9cfLpJD5h4+VMr5k1UIKrsUCvIS1SM1Vs9D0UX5g22gRKx0NzTlv7xgb1tcksg5I/1uguDtfovUrg1jLEY3s66GcbGUyBfCROzBxHU05cFOPBB7Huqmy9yuxLvYq5SYZGKByj5l05kr9BHXMNOZuHHWFZvLNNQGsbYNsZOluOJOoSeLqOqJ9Rl1yWlSz21kHSYJjXXK3rU0qSIHs/MipB/F8x3mm7V7sOE9Q/jXMJadrCxokdKDP4IvHJhULSuPaFaPnqc+5/oexinWDQrbgP2GA3HqPeBrm0LSohbIY20A0g7byX8oSXO3jl+H3/8hp8SFCU6Dk0r3qm03znJEazEHZj6hO/YNZz3faFBP24eutz+26oiLFlZ7AuGX/kydi17GG5+GIVPtLTYEogyQ+/EnZmhg+xkToZG9YWitjoc8IOj0mSel7rGToiwtbjbJf/L0p+vB36XX3CkpNyPHrRrvIU5ka/stTXiVVVW5X2TluzeLa+Krfn/BfSAXoO24WMr4p/teTIypQEWn/EA2Mb/mWujVhH7IiIwGEQ0PAnGOtNPBZzvmNFctzZZxg3MNgXuZsgV9giX4jSs+xVH2S8zEDrgoqf7Md7Tyw7fp5hIgODIvxA8w5ABXXHj6cxzbHfTVla/cnnWI5kZtrGgXcCIP72M8+TUV3cNO16tT/Td+yavNEUA+WxGeEQEXC/1t0351yfWcW6YBMHnMz8uzN5y5aHUsPBngboruLNozLWwRwUMzh+cJ/ceSPByDWXf/jrpNPJ4kYl3+ePy0y3u1GY+55xCD28xrneXq31Rzyh277UkAd6SxDjysxS8O/0T1hJQ5qBK+Qndry/QFz2Fruhggr/81/SgmdKcjUDcYw45WTCiByb9NtfftPCj02rK8AQffGW0qThNeIuFg25s233MU1npNtKJHRdolkpQBgfXu7R+oTbpDRwLZGiNX7LEX7KEJw+FClYzYlQrTffs+a0ggf+CpgCl0igPeGnb2yNgphYQ9lJfd85u4SQSx0ldY2jvb4vkDrg2QF2hXnZKKTgdY1KE60IEjptpgzGe1g3SRRrs/vgDSS3sSaO9xfySqrL3ZyH/Ch16XYkcGU5LaqPJ0M9RpljiMqcENHx4S7dmhtxi3vynGweNEV7RYMGL/0538lRf6+mL1tR70oBRXTANKQSJGMtz7YmK2Zf3ej8PHP0uSOdr30EtbWb1dp0GP5MpcpFs8FIqTzLlOw+G0LC0UOyLVgFVll12HJ/ncchnSMjk2LM+h34P882qwI5G0DiycAGy7sRL6Rw4mR1aKweCUgl6ls+iehg0tgehkktr1TeuEiFyRW/5yRqaZwisQOQur+4TptQNFXb1nXWxfL/2DZJ542HDjF4TnAGSXX59G4iN90HBL9UrX/o3l0vvfuqeG8oETyjGptJkV9RgNdcXfgIEqu/xuUkZBymbqflWopaCh3brS6JB4q4Ewd+6enDKwg9HelprdgIeD41oJewxTnNbQId5pNlhFpBznuuC+VTO5Y/n+qkV/s6ZLsj9/ZbRojOBjwkjlCisYM7TAWuTtaWohluyMzo08sb+iFp20MEVQp//C6FfV96Sd/MigbA5CxHzswlZusjOwfYur7uMuHLiICprsRuuDfjEqPytixP+qtKk6+MhvMeO8L/uylLQav3GMwlJswkOuF8Tj0cOgQigfIt1LPle18mlaDc3nyYw5mLdN+Bbd9lTeBJTAhy9VD/clu42A4YX/2IU3OoRfUenGFS7BuiWIvKcptqmCg2BR0m9Wn+U20OXvf0rMvOObVXXOkIdQBiIyn7TzXORkGzIrusORlgmmnjp7ouMQTqPXwesTgFIkQlaP+yWHcI9Pu9XEgjZAComRrWkNOhlkvuEFHhbL7iA5C3kzOz0Q8rw0izSEsvN9bROwOolwiO9gKT5eu7TpVzejqHK30v2Mh6RvpdTrqjo5v2vvfR8gKQf40Mq6Es3QraC1FMi6qsIB7oW11oR6N3MmTwF1us4cGzsOxboB5NzW3vLlmAPLnKuvbigh5XI71x0S2RwPuK4eSoqVHSadJqcFB+0kMzEN+ldFHoMN9bxFqAZ7tgp1MCrM335TKJhHyt29qY5SZZJ8wq9/okopiEB6hQT4wzcUEtyU4TEVy6oUuhT8nnNupWgbhiyW6/PrMd5XcTMDSeeA+QjC/0wiCEHRvBtci7kLrMJElXzK4W/vfh0aks/vyZZfWl6SrYeMgyIR9CqTVHFDquyqWuuIYbKqAkiqvQcJgyWacdyJSnYNnLHIMi6LYln9Bzpkg5v3kIlNmEk7ChVvkSABE+V2vNUXplbI2nA9Uqe6wd/o/Xac7VNWADOEJS1kHYkVC/KtrHSyfzYVnU4Iybt6v+TBzT0PgGlIwWHWeXb5+ffjjzn05YeeHNDlLvCIFxvz2c70+YgY3Q+/425isSV9ZwxulLxPXrGulBuHhLBv1DnkKTolhrBnc57C9CaGTXfuQcPoJcbTDxGkT/SHZ6sHf7AI4mvvEcHrNyesBkStFfr3M4pi/uTeTO8bYb2O/106Bgzo52kwcRxNBVt7ZDmOfYvtr3v0ADFqQfUvwdn8W7jSLJsCEdhAs7P3a+U7leHCvb38eYG+CxqoMZjuk3tQ7S/BmJ2m0CzyrM9lFADmJhMVy2Pm1TDtUzN3Gz2ouu+TJ8TuO16MhIvT2NE3fCC5c7Xh9NnSTNmcjl2pUY/9p1mraz5CXfbb5P4W8ZRymcRoueTtFzhJMjqNISeamLfqDi3o92xL3pIv2LayjixkIdcsXzsXzWJJitku/m3KrnKiCLTd3LMzE64os3ch/d0+KnH4DRlJVQDFkx82AtOR19FuhixGnS/PoSq4j5UT/LSJhzvv5okjWK3v03qm6mppwjEcwcGmMFmUoyhjBmpjDqg7gE5Tk5lTRw2SIVsWUqHXNQCsmS5fPJ6LcMUD7imLzYo/+yHofNtIYAY+6tB+x60wF0oTj8f38GzCGUKcIq1kRQE+m/jkK6egWPOxZLhPKCj9cQ4vZ6uBjlP1zBXeA56oNYdZX5ZLOwbFskjUnAhkZUmGpJuf+dpu5GEVGv/YMVlU+p2C2XjxvpmFjm4kkJk90PO1jE0N7KnVWVmVNPXxW7DQ+LXlS1N79REuCB2mL/sYskMRMwLjgQfCGHjvpe3EoUU+tvNFZw7H0QGyd/KMvxd6cc9OgIUMCUoDOEYVLnUK5KOR7sU28urcPWgAfMZ51dIsswwZyDz+Hvrf4GPaUT3bqPmhhCRc1cGANU0N6Zm3ab//nv8RexxRv9nm7jLZgLseksVRUxr8kwNblYfIpFyIFTY22JjdYv5fT2m+5GS84w3fQL+lj1z71I+DjkI4twUmK9c23ckmJqSpTBlJMkJJ+Vje664Wy+snKYo3oZCvEJsgf5YriW2WSj4sTKddh4hHtFB2sou48cMgMnkevqSRRtoXHVCdwMsMeP+lBrjH7WGIaa3A7DVEvpkLBK8rWidbOK0+rDmys0eFnl1eAYt42+/7lQ0UJXozRzcSfhhQ2XN5Rw6fILm33MjqjemTUKPMR3MwX7vH1q8kz1yeUvS8f/XMTictkrxHDRfkxys7C0dDK6JnhuVALAO2nQGyIGoB/joy2t915AeRU8RwPz0IqT0fTc51uXvQbLmlUyHJJwnI3AV5hKDkrEdam7J+5wfJQV+EbFF0hy+Q6Es7GkJkFoIKaC/3Xm6HQhZhXZUyjLKKWho42TA7w7lkRFn6LQCzNtmgoh5TsPyjzr5PnIFyYM6GPzxGare6jk+8U4PTqlypzjStiEI8TwxG9ggXH1vVPobXpjVR92figxhIC7YdR9lL6e2Erw9tekvyQuRVUSaTEOxOFjyVMMbYINHNuWTz5sEZ3t1Lyy5JpaOl1dNhpqFhtpRQSzDoNuVbgfqDRrQ5n6TPkP+Vj2Iu3BWSYbntjfyEnB3KM1TNFqjAZI1syD4WCkzu5dvCPjBNRJ48wGQklmeas64mToopg3ehHeCVXKwL3nqtoE3dk+OXoCNurumEQyJtgGq5Et8N+kaWUjatI6uJ6x3DnxOLtrynhP+7wRBYmYEWT86eHEN6Yc6f8prj1eRUe6dyQZh9spZdGcU/TmzlrEE5XcEX3EJVb2ik9J3U2DtbN9mgrJYel6N1C8TBJCzDvYNDOI0OaBrBmB2EJ7B1Y1iJhwEHRs6nVDWMytQa9QxIjCaMYQqZYcHK44iNVUhCDZK6pgckCnXqJf7z+KRewqG44Jv2AUoca9XyKpKbLHfpS2viaPjo2TDBkbL/GLkeeCH75moAovHO7MMOBSfFpfaglCqrMvCbyUSs5o6/gXZgs6InAjPxhoDbW6NUbLxTGtiiRA1/UFMIFh84bBNlPYwi4IwdtXHXdMpMiKx0uDx7Fjef4O6H4JJ54JV6NaqDFSm5I7Ez9qSVKthx0VOO3y3+sFHBZlkWozqFDWGSC8AO30xJMURMTEUv76+lJ7I0yjnp+S0pDiKU2Kt5gJCWjEe6dBcBS/RUORVV/rcWC1V2TvudFJo3C7n4OaxHS7Vlovi1fVtXDhZXeFXtgRRY1rCQJSWZEvZNn1Ik0VqaIig7fRdKoUCUjbc+cJ9e2bVIzrmph5LuyDfYT63YrwyjK2vfxBOlPczJ9Hts8FyYqHRsPgZKTiEyaxHQaDkngxHKgDUfCIiqu8tveROpjXFrKg+mlkisCZ2XmBCAAGcfJ+A5UON1b+/GELQQJKor2hThdxkKsbjnxENLrG+8K9X+iGe+3trrdmE9RspxPFcDRlTKD9sbrwCOJzF8qJ42oGctZe9vEYR1SOxBie2kCc9iNT36dpcW+cwl08eTun40qIwJSeaSqO4c53L2P6A6DTqD3RH4RSTsjhgK67GUYlSbo9qICB8zOalq9fQV/GBVXOqfxeH5FdTqskgvHPvgFYNG1Di1Nd/azRIUuJ7DcfzbtsezHmYeoXYiRwCJsAHafFwvf+DSrITr0p+8HZbHYSrNwmQxFIgorD5tQujNOhlL0AVo0OEiS7d5tN0QXjKsw9wqDwKouuOFT8jNHRiefFgWR+nuX5rH3x9HQabagLg+HnNCOvl1rvpP7Oe7oLtSObopfVsyQasHg+bg+UmJoJob2sLSzBQd7u7eC0lYbXEhyWzreSTqSttcUrtP8fB5Yu8jx4QdI8p2jMy6VTYLhYK3/2PP84JjdAkxzP0sgDaw79WQTtksIQZvtKBV3xtbFQiHL4lz9UO3jcJ42wAqVKTh1OHMb1YMz6WHkMrsW0wfCNEPxNpNcl3FvjVKpDtwkc6dfhZhzAfbLBqbgK5ypJJUi49YovzLCjjTv2dy9SRztlZd+JqHuOpyjgaXJZbUz0+oJkUe1G9Ne+S4lZUR/gGsWsXK7NhpVoN9C7pxuU7l0W55wwvVo1IsKjsmfpcV+Xp1lc8NGb0DRpUVOhQ2ss16DjyDazdZORbAd+zKFRcyFjXPIeiBScB3Y1oaVfYMhbEgJkqDtcIeMWxzEZp9Uz1a3zYRSXZaNyPHj0VYjEASR0UJ621pAGV5VtTXZS2+MtwbLMcHMgdSvtQtWc4idVB3XPQhZNBpJwyVEj9TFnKL28bsiKOo9Gka3up95sZbOZlXnDGN0zuMiMDXv4Dvp8or5wGxhpyOt58SFt/iFWF/KmJCS4tKMbUq+S7nIMjUKEpGxhO/0iWiq8mw9gRP96k6/e+vAV/ZfDGhSiMYojMjmaHoCa/Wt9AnigN/R6/4tjN3OTHGcUWmauMUQkRj1NccJsJ6DElE8+rbnZQ97DWXlnzRxVxWkmx0WGVIOoRkc3ZSu6gkK5V4lWARlBnnADdd9Axu09PZGw7OsPeDI1TWhc3Da51LsRatNbRda61c/ncOAUFpAio3mHX5IPWCIJGwy0E6fb0nHNQ07gpP6C/NUfS4efxt1z2Wr5JG0QFszbKpmFZRyvNhush65Adnf501A41B2NVxKoVpCq7KsgmujDk90zIsNDXel0z8vipZPk+g28O2JNSZpzjlg4DlXf6U6DpdvAmFhEllKIYa6KyYjUinuEdW/O48dzSuhtn4BFFAtK+8JSJmPfwC8IC0lXUBCu5K4phttBGs/cQV69Kn1Gxy6idyUDTApGFgibo0iWC6OITMSFW5b+Vc+VxGbGtCuHaj1kK4iXi9gTOV8UHssT5ZzPeBqubCiFwstIBEr5ZLlPmxxyMKBevPJNwqHmaR/FAQ2/fDBerXjpAC7WifgBn3e10YS+DJD8zd1GRx/8cz0NV9vi3ru7Jri6Q7zk4yJscjNQtEytzXX9S8rSJAJj+xke348sMXAmzuFdpO7v3+OP+Zp/HTY1sy9BOKjKnIys4lmLlMomaWqKZ1m8rrpfo6gFEx/v/ofQHSvyLI1E2lyYi8GdNXajI7HuxQSmnPYFtN7LPw8H/e6wbduMwzdbKxJ/Er5h3XNWikCIY7b3zo3OTSrBDynSvKs/RXccZouWy39G2TcKpMb8AQyt/5jC5HLzLTy24yGtXSr6RF+Kr3W+gWOvN4Xhfo6rMeHEAv+bJUzju1Fgdv2t7k1NWasn+yohJxKUIlDgvnfMgsP6mgaeT5cfxXMRVGNV92u3cfAfvXOZHt+E3MPtCuEuPxwUZUkQmTu2V1p9RVk7gk35l+WM+Nj5WreYmEHPqIgtyB10i0S9r7ttcpenvZJ84Z/mPr+7qUKPXg8sLeK5H4WpMbmbFXNeayrOVERqX2mpU8IhIMSsmrcp52+3Vs2VHx1qLD6Z7JZ9bYkGJ2ZpSZyXZ18HgzJBIAh2fmHvLb6TDzcckKKymqGyM5bIuf+D1ieNcrW0qQJ/fEYP0owLfQBy4Ngt8R0pHoT2YhQ+aOIdXbbTwp4Yw72X4inYvAKokevAVyFK3bK8gTvI6CAfxRDIhpZNdIAix+YrS7CJCfL6Bj8H11zkiupLHGXjfg9Wfra2uDh5n8UTFUZ+Ms+VPoUXi+35EsLhjmC6NNn8qZKIhJiU2OIOzUNXC6BK0D4yKMt8rqD8Dm/J5+YR2XFlZXnIhdOnzk8Sm4mxY2IFDuxZIBajg1v2yhrvBYwiMO+EjiIxsu2lDr8N/qCGHa2hplMFXtH409IEaoIWeo+IvtkBP/iWLCinIaRSEZ9sYT5kEjvbjiUb6i2bjO3sDN4x9l3Zr7s+UhAHjGgI+GAOJlKQFm2P6MtD8d12PbGRxYpjxg6vu7fMhRJ1NsCc7T9Erl5ZMnE/ECCA4hBmZE0O98iJJuQtV6v3+Hf80v79e7CgB/l8BqzKXbMuFVg4fl9QpeKcYKCAHNlFYkQ0z/Ec9hUak0TAIE08SJW7AmECvDvG5p3nJ9+F0UcWcYTaNGNZFdhPYvn1ye5BRUvt5309zPfGWYIv+ysZrkRN/BNEaKHjwAaoIi0kJpXgLvwEnyy0vGVRRxFoRwfC7WyS5wnAQK/caBUu1ZH4v8fjB2dC4WWBCddlaXOpVLChadDGkr29bMUYbVQRGNiugVXpQp7MZK4BGDKZPBD8rTfTh+AdUarSd8Jt3s4j9HkH2tZ/BbAcu8l/M8V3l5h3xRYuCW8aW6shAig4Hk4hpF/Eht1x8kfaqIWVkk6ib9IWgxRmMg6OMM2NwxmURfuC8L+fye6jdeAxe3IC/cLKA/dp2QQQ4cCtV3o78ymk8koFyw79EuuOZP0/tDh0gXts8zWdzAL2qahAQ2eE2lNpI7uWZZ5w2YGk154IU5XbEmL7k2muE0I5Ad1wsqLKJLVjg/EPbf6rPkrgJYS3ieVojTF3ZmLvNleiKoleWVdPb9rfx7HhByl88pSZaGHogbRXzjKYjVb+Ayw35UVmnpq6V317xpnG05PfY6T4jU2nvG+K0nElMxVg+7yUzQCsDZxU6YtE1yz7Et8Zg3Zbj0jXzQDhOmLQNyLF4hc45cKS51yASWDPnNZ2KlIrTacqxjqWmk7Rs3fHnTqqombjK8obcm+K8ZIdJGpHltZQz0fMawAawT283Ifsqzz2ou5u75N5MHd1TFURv/6cv7qDbypnawjIPX9B2nPNu4nztiHowXKFJUY2IkqjEbtVl0zcEX0hsm8HkLoLYY5nUt+Z91cNOuyEQ+D1vQabSLu/aJfDRK+2GuU23/8oJgRknaUpS3H2LCQCKZqfdeZjlKJ7NPu6sJoSihWtf9heWk2C5nC8ZrL74/OmrJDUQ/6DYrbSUmmMV/h25chAffgqBDx/v9I8m19y0XOm5Kx27tBHUqqav7Md/fZDqWOwGBMYDdPPA23aIjmF9MfEJQIcRnSxBHPlGMZ6s5AbNBcKuqjBXNTvj/fwy83yRkU1/7hkY/BJHMPkKjJwxrpUkQQ6+RCr695FFATiPWoemxjhC2XpYWf9zZdTZlTedurASrghIQhUe5bkx7uYuiYMNO/BwF86LEVOC+ZsKqjV3ClPMgDLGxpUHI+h42hQH+ydMB8xHQyo0lmBaOWhYcQ77k3+BgOTX/68nWclQRrtWYCa71Wa6G5iZLrov/+OMXDQn9Y1DUAl5fn76aC+1BxyEiAWmazmi2CIGiY8Db4o94BgK6BqvcnYAPD32VXeVP1pANQO4Swr9/YBcIjXpltTLfUopVW8JvAW1IuHCtF8DKIZgc+vfqzibNz0T8qavB4jIoLwHDqoz12k2zMFuh4VhMg/ojToImJA83LvwGBn/rnThibymrARBeEpVrivMObINFkK/pAn4jzV0+KMDEUwJ5ljL0vuLqSfEtUBJPkZhUIFkfPM/rIGa/hrn7QZlN4nms2f3/iWom/hPzPC/g4z+RH7on8Tb7PLnXMEGyayrG5TKPKz26mEcTvRADmXeB4yASDrENnbBZo0s2pWkCT5QA6leIFS/Niz1O6R5QuTpUPQuvoiW4PDUTG1f4tzTCljUM6sacjuNkoqUWWZxy7U4GFvVthWBGcPbMGbM1tyrlnhUi+8suato+VvXxoQJN+3wb18cZn+hm+vVdocJ0zae0ZEiXGjcnd/sW3XwR7IV8rX79AsFxAYkKqBDcTW2GG9b9jpKcgpAJmgfb36CrKyf18QaO8TVGSNT/YKX0XMZgLFc85yR1Tnvolcg0Z5xFmdridrB6gU5nIBxQ+EPnWJJkFDftJpBx4YbmsVHjAZxecLa9YrffOjDbNZganTW/wylmR8Q8wp/OoCo7nA5ItHsZjkzfLjlxOjPhwvvQxwRK2xaCYw67DXoU1WL5JritPM8quCeRz8/3N7/m6r7Z8YasV4Nl76ku+8cAJv37FoN1FfkDELKTylDjsfUqgjCYcZq3KoE15l/CDzinmMxShDfMzdkqPCeeMG6AQfCq/wTz0fkVnvkNc1x7QYTjMvxShYq1zKNzNOfsbVqOmMLcmVgplo1gbA0qbmXbjZD+FbfpbjE+FwPbsxKb39qT2RD59y07Uo6uBtttuRAENlfMYCibK/TFewNj5CgJWgAq4pk3kDRHWtGYiwKrzxY7yf5CiUI0wqelSFjGnSfiQ2lyqvmO1LMWg1WKXfnubJqNzVLTN8EpcdiSdcM4of9ZHTcrl8yTlChYUCgr3o6L21QQovftVpAtx/MCx79RwdPePtUyXoYQJ4BAjf00vjCaCIZIYBKom+0sLIm/NTK81m9TF0MndEQquJnRPWRFj6w4DwJJCpuGn+IE24gcnt0Rcx1bHoZ1vEGQCwru9JKaqBMaQLkU9QlApS7kuiXaFEldy289QOcrZ1FQYy/bA2CP20POxi9EeqV4vsMIwIEkctPwgTOg57qUCObs7aEq0Suk/4RB8JAPCftq2kJ6EJlb/bOORTteRqubFhY6OUgY8fV+69CYm9UN2SkQt+nReah9/nr7MEwnBnoZlXd5mlPO8lMZJv0VzuV0gahazEUmbbuYNp8cste4CkFIn3zPowSCJ6KfbTdCGOF8TglQ5cEbBD0pZSvoAbTk9XqLOuhGg+39uwbqLT9KamwMD1Siiy/oQMrvdi3xwq0Sm7XVYEttfMNkB3KzSSj7Jq7k1lLBTRnPArYeks3cQjm2ysa1IUuDF8AUQ9fcVxYUKn0ZZJI6jAcUw13IDs55D6ecXiupczd4gAVhpTUTY/bZMzqdiHeo0D5Gq2hSNAh8ofYmMHdpC82orVP8vLEO7G3gCnG7stylzmMCjzs5VTvm6u5/h3lOYR85xr3aXZv2rR1xhHSgr255ZODRJiMRrJSchgPPg2NF0MFe6xySQjhSFNSbvb4q3zAuuUAWR/zSQEGpzjLuPpFg8uCTKGE7UuGM2mZxn8AqjvTed1gx4WEBBGAh4u+IsLMEPkWu6TIwTFHqtVDZn2ntm5tIekR21mBjr6qXMGy6s7TqERabf1XncOG34Sr0GvPUHFOk0k/ZaOE/aV/wTW6JI4A3HawGJmpaZH+fapwQePakJh0F7qP/MmpPphuA/FmBWU8PjZJfR7nJb7K6aFaDBXkX0EpC5vWk=","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"975105c33e75d9a20ed621b0f24ec7b26887bcf8","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"454-571","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"a349b2a16820229804f5cce2c44134cc50d82ad7","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file diff --git a/02-SERVICES.md b/02-SERVICES.md index 81fa11e..eab2645 100644 --- a/02-SERVICES.md +++ b/02-SERVICES.md @@ -97,7 +97,9 @@ class ResourceCalculationService $pendingReservations = $this->getPendingReservations($node['id'], $excludeReservationToken); // buildNodeAvailabilityFromServers validates complete node/server - // resource shapes before calculating totals. Stock Pterodactyl has no + // resource shapes before calculating totals. The fetch layer also + // rejects duplicate node, server, and location identities so repeated + // upstream records cannot distort capacity. Stock Pterodactyl has no // node CPU-capacity field, so cpu_threads remains a fail-closed gate // until the explicit local NodeCapacityPolicy is rebased from PR #22. return $this->buildNodeAvailabilityFromServers($node, $servers, $pendingReservations); diff --git a/PROGRESS.md b/PROGRESS.md index 8edaca6..88890cb 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -77,7 +77,7 @@ All dp-NN backlog items are implemented. The active reconciliation is staged on ### This Session's Changes: 1. Preserved the dp-20 panel close-out without restoring obsolete deployment guidance. -2. Reconciled the location availability path to one `locations/{id}?include=nodes,servers` request and fail-closed capacity parsing. +2. Reconciled the location availability path to one `locations/{id}?include=nodes,servers` request and fail-closed capacity parsing, including duplicate node, server, and location identity rejection. 3. Replaced caller-selected SQLite test paths with the internally generated `:temporary:` database workflow. 4. Migrated the retained Qoder page set to GitHub Wiki and synchronized API, deployment, and testing contracts. 5. Published draft PR #23 for exact-SHA review; Mutagen deployment remains paused. From 1382e8398b0a592ec7f3d454b60c5c568f0e3a3b Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 22:25:23 +1000 Subject: [PATCH 22/95] fix: verify complete capacity pages --- Services/ResourceCalculationService.php | 67 +++++++- tests/Unit/ResourceCalculationServiceTest.php | 147 +++++++++++++++--- 2 files changed, 187 insertions(+), 27 deletions(-) diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index 5496d10..8ceb6c1 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -336,7 +336,7 @@ private function fetchClusterNodes(): array throw $exception; } - if ($exception->getMessage() !== 'Pterodactyl API returned an invalid servers relationship payload.') { + if ($exception->getMessage() !== 'Pterodactyl API returned a missing servers relationship payload.') { throw $exception; } @@ -408,13 +408,15 @@ private function pterodactylGetPaginatedData(string $path, array $query = []): a $page = 1; $data = []; $expectedTotalPages = null; + $expectedPerPage = null; + $expectedTotal = null; while (true) { $payload = $this->pterodactylGet($path, array_merge($query, ['page' => $page])); if (! is_array($payload['data'] ?? null)) { throw new \RuntimeException('Pterodactyl API returned an invalid paginated data payload.'); } - $data = array_merge($data, $payload['data']); + $pageData = $payload['data']; $pagination = $payload['meta']['pagination'] ?? null; if (! is_array($pagination)) { @@ -431,16 +433,43 @@ private function pterodactylGetPaginatedData(string $path, array $query = []): a FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]], ); - if ($currentPage === false || $totalPages === false + $count = filter_var( + $pagination['count'] ?? null, + FILTER_VALIDATE_INT, + ['options' => ['min_range' => 0]], + ); + $perPage = filter_var( + $pagination['per_page'] ?? null, + FILTER_VALIDATE_INT, + ['options' => ['min_range' => 1]], + ); + $total = filter_var( + $pagination['total'] ?? null, + FILTER_VALIDATE_INT, + ['options' => ['min_range' => 0]], + ); + if ($currentPage === false || $totalPages === false || $count === false + || $perPage === false || $total === false || $currentPage !== $page || $totalPages < $currentPage) { throw new \RuntimeException('Pterodactyl API returned invalid pagination metadata.'); } $expectedTotalPages ??= $totalPages; - if ($totalPages !== $expectedTotalPages) { + $expectedPerPage ??= $perPage; + $expectedTotal ??= $total; + if ($totalPages !== $expectedTotalPages || $perPage !== $expectedPerPage || $total !== $expectedTotal) { throw new \RuntimeException('Pterodactyl API returned inconsistent pagination metadata.'); } + $calculatedTotalPages = max(1, (int) ceil($total / $perPage)); + $expectedCount = $currentPage < $totalPages + ? $perPage + : max(0, $total - ($perPage * ($currentPage - 1))); + if ($totalPages !== $calculatedTotalPages || $count !== count($pageData) || $count !== $expectedCount) { + throw new \RuntimeException('Pterodactyl API returned incomplete pagination data.'); + } + + $data = array_merge($data, $pageData); if ($currentPage === $totalPages) { break; } @@ -448,6 +477,10 @@ private function pterodactylGetPaginatedData(string $path, array $query = []): a $page = $currentPage + 1; } + if (count($data) !== $expectedTotal) { + throw new \RuntimeException('Pterodactyl API returned incomplete pagination data.'); + } + return $data; } @@ -478,7 +511,14 @@ private function requireRelationshipData(array $payload, string $relationship): ? $relationships[$relationship] : null; - if ($entry === null || ! is_array($entry['data'] ?? null)) { + if ($entry === null) { + throw new \RuntimeException(sprintf( + 'Pterodactyl API returned a missing %s relationship payload.', + $relationship + )); + } + + if (! is_array($entry['data'] ?? null)) { throw new \RuntimeException(sprintf( 'Pterodactyl API returned an invalid %s relationship payload.', $relationship @@ -500,6 +540,14 @@ private function requireNodeAttributes(mixed $payload): array $this->validateNodeAttributes($attributes); $attributes['id'] = (int) $attributes['id']; $attributes['location_id'] = (int) $attributes['location_id']; + foreach (['memory', 'disk', 'cpu_threads'] as $field) { + $attributes[$field] = (int) $attributes[$field]; + } + foreach (['memory_overallocate', 'disk_overallocate'] as $field) { + if (array_key_exists($field, $attributes)) { + $attributes[$field] = (int) $attributes[$field]; + } + } return $attributes; } @@ -516,6 +564,9 @@ private function requireServerAttributes(mixed $payload): array $this->validateServerAttributes($attributes); $attributes['id'] = (int) $attributes['id']; $attributes['node'] = (int) $attributes['node']; + foreach (['memory', 'cpu', 'disk'] as $field) { + $attributes['limits'][$field] = (int) $attributes['limits'][$field]; + } return $attributes; } @@ -529,7 +580,7 @@ private function validateNodeAttributes(array $attributes): void } foreach (['memory', 'disk', 'cpu_threads'] as $field) { - if (! is_numeric($attributes[$field] ?? null) || (float) $attributes[$field] <= 0) { + if (! is_int($attributes[$field] ?? null) || $attributes[$field] < 1) { throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); } } @@ -540,7 +591,7 @@ private function validateNodeAttributes(array $attributes): void } foreach (['memory_overallocate', 'disk_overallocate'] as $field) { - if (array_key_exists($field, $attributes) && ! is_numeric($attributes[$field])) { + if (array_key_exists($field, $attributes) && ! is_int($attributes[$field])) { throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); } } @@ -555,7 +606,7 @@ private function validateServerAttributes(array $attributes): void } foreach (['memory', 'cpu', 'disk'] as $field) { - if (! is_numeric($attributes['limits'][$field] ?? null) || (float) $attributes['limits'][$field] < 0) { + if (! is_int($attributes['limits'][$field] ?? null) || $attributes['limits'][$field] < 0) { throw new \RuntimeException('Pterodactyl API returned an invalid included server payload.'); } } diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index 49e13c5..da11d1e 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -39,7 +39,7 @@ public function test_get_locations_returns_parsed_array(): void 'data' => [ ['attributes' => ['id' => 1, 'short' => 'us', 'long' => 'US East']], ], - 'meta' => ['pagination' => ['current_page' => 1, 'total_pages' => 1]], + 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], ], 200), ]); @@ -315,6 +315,23 @@ public function test_location_availability_rejects_negative_included_server_limi $this->service->getLocationAvailability(1); } + public function test_location_availability_rejects_fractional_included_server_limits(): void + { + Http::fake($this->availabilityHttpFake( + nodeId: 5, + locationId: 1, + totalMemory: 8192, + totalDisk: 51200, + totalCpuThreads: 4, + servers: [['node' => 5, 'memory' => 1024, 'cpu' => 50.5, 'disk' => 5120]], + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('invalid included server payload'); + + $this->service->getLocationAvailability(1); + } + public function test_location_availability_rejects_server_for_unknown_node(): void { Http::fake($this->availabilityHttpFake( @@ -397,6 +414,22 @@ public function test_location_availability_rejects_node_without_cpu_threads(): v $this->service->getLocationAvailability(1); } + public function test_location_availability_rejects_fractional_node_capacity(): void + { + Http::fake($this->availabilityHttpFake( + nodeId: 5, + locationId: 1, + totalMemory: 8192.5, + totalDisk: 51200, + totalCpuThreads: 4, + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('invalid included node payload'); + + $this->service->getLocationAvailability(1); + } + public function test_snapshot_falls_back_when_included_servers_relationship_is_missing(): void { $calls = 0; @@ -410,14 +443,14 @@ public function test_snapshot_falls_back_when_included_servers_relationship_is_m if (str_contains($url, '/api/application/locations')) { return Http::response([ 'data' => [['attributes' => ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']]], - 'meta' => ['pagination' => ['current_page' => 1, 'total_pages' => 1]], + 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], ], 200); } if (str_contains($url, '/api/application/nodes')) { return Http::response([ 'data' => [$node], - 'meta' => ['pagination' => ['current_page' => 1, 'total_pages' => 1]], + 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], ], 200); } @@ -430,7 +463,7 @@ public function test_snapshot_falls_back_when_included_servers_relationship_is_m 'limits' => ['memory' => 1024, 'cpu' => 50, 'disk' => 5120], ], ]], - 'meta' => ['pagination' => ['current_page' => 1, 'total_pages' => 1]], + 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], ], 200); } @@ -443,6 +476,28 @@ public function test_snapshot_falls_back_when_included_servers_relationship_is_m $this->assertSame(4, $calls); } + public function test_snapshot_rejects_malformed_included_servers_relationship_without_fallback(): void + { + $calls = 0; + $node = $this->nodeWithServersPayload(1, 1, 'Node 1', []); + $node['attributes']['relationships']['servers']['data'] = 'not-an-array'; + + Http::fake($this->clusterSnapshotHttpFake( + $calls, + locations: [['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], + nodePages: [[$node]], + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('invalid servers relationship payload'); + + try { + $this->service->buildClusterSnapshot(); + } finally { + $this->assertSame(2, $calls); + } + } + public function test_snapshot_with_single_location_single_node(): void { $calls = 0; @@ -543,6 +598,9 @@ public function test_get_locations_rejects_non_advancing_pagination_metadata(): 'meta' => [ 'pagination' => [ 'current_page' => 0, + 'count' => 0, + 'per_page' => 100, + 'total' => 0, 'total_pages' => 1, ], ], @@ -567,6 +625,21 @@ public function test_get_locations_rejects_missing_pagination_metadata(): void $this->service->getLocations(); } + public function test_get_locations_rejects_truncated_page_content(): void + { + Http::fake([ + 'panel.example.com/*' => Http::response([ + 'data' => [], + 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], + ], 200), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('incomplete pagination data'); + + $this->service->getLocations(); + } + public function test_get_locations_rejects_inconsistent_total_pages(): void { Http::fake(function ($request) { @@ -585,6 +658,9 @@ public function test_get_locations_rejects_inconsistent_total_pages(): void 'meta' => [ 'pagination' => [ 'current_page' => $page, + 'count' => 1, + 'per_page' => 1, + 'total' => 3, 'total_pages' => $page === 1 ? 3 : 2, ], ], @@ -602,7 +678,7 @@ public function test_get_locations_rejects_malformed_location_payload(): void Http::fake([ 'panel.example.com/*' => Http::response([ 'data' => [['attributes' => ['id' => 1, 'short' => 'dc1']]], - 'meta' => ['pagination' => ['current_page' => 1, 'total_pages' => 1]], + 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], ], 200), ]); @@ -612,6 +688,24 @@ public function test_get_locations_rejects_malformed_location_payload(): void $this->service->getLocations(); } + public function test_get_locations_rejects_duplicate_location_records(): void + { + Http::fake([ + 'panel.example.com/*' => Http::response([ + 'data' => [ + ['attributes' => ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], + ['attributes' => ['id' => 1, 'short' => 'dc1-copy', 'long' => 'Data Center 1 Copy']], + ], + 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 2, 100, 2)], + ], 200), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('duplicate location'); + + $this->service->getLocations(); + } + public function test_snapshot_rejects_node_for_unknown_location(): void { $calls = 0; @@ -679,7 +773,7 @@ public function test_snapshot_handles_pterodactyl_5xx_gracefully(): void 'data' => [ ['attributes' => ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], ], - 'meta' => ['pagination' => ['current_page' => 1, 'total_pages' => 1]], + 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], ], 200); } @@ -742,7 +836,7 @@ private function insertPendingReservation(string $token, int $nodeId, int $locat private function availabilityHttpFake( int $nodeId, int $locationId, - int $totalMemory, + int|float $totalMemory, int $totalDisk, int $totalCpuThreads, array $servers = [], @@ -833,12 +927,7 @@ private function clusterSnapshotHttpFake(int &$calls, array $locations, array $n return Http::response([ 'data' => array_map(fn (array $location) => ['attributes' => $location], $locationPages[$page - 1] ?? []), - 'meta' => [ - 'pagination' => [ - 'current_page' => $page, - 'total_pages' => count($locationPages), - ], - ], + 'meta' => ['pagination' => $this->paginationMetadataForPages($page, $locationPages)], ], 200); } @@ -847,12 +936,7 @@ private function clusterSnapshotHttpFake(int &$calls, array $locations, array $n return Http::response([ 'data' => $nodePages[$page - 1] ?? [], - 'meta' => [ - 'pagination' => [ - 'current_page' => $page, - 'total_pages' => count($nodePages), - ], - ], + 'meta' => ['pagination' => $this->paginationMetadataForPages($page, $nodePages)], ], 200); } @@ -865,6 +949,31 @@ private function isPaginatedPayload(array $payload): bool return isset($payload[0]) && is_array($payload[0]) && array_is_list($payload[0]); } + private function paginationMetadataForPages(int $page, array $pages): array + { + $perPage = max(1, count($pages[0] ?? [])); + $total = array_sum(array_map('count', $pages)); + + return $this->paginationMetadata( + $page, + max(1, count($pages)), + count($pages[$page - 1] ?? []), + $perPage, + $total, + ); + } + + private function paginationMetadata(int $currentPage, int $totalPages, int $count, int $perPage, int $total): array + { + return [ + 'count' => $count, + 'current_page' => $currentPage, + 'per_page' => $perPage, + 'total' => $total, + 'total_pages' => $totalPages, + ]; + } + private function nodeWithServersPayload(int $nodeId, int $locationId, string $name, array $servers): array { return [ From 0afff90d2481ce2d1bd88f959433eab677f664b7 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 22:27:15 +1000 Subject: [PATCH 23/95] docs: define strict capacity boundaries --- .../Resource Calculation Service.md | 7 ++- .../ResourceCalculationService.md | 13 +++-- .qoder/repowiki/en/content/Deployment.md | 2 +- .qoder/repowiki/en/content/Testing.md | 1 + .../repowiki/en/meta/repowiki-metadata.json | 2 +- 02-SERVICES.md | 57 +++++++++++++------ PROGRESS.md | 2 +- 7 files changed, 58 insertions(+), 26 deletions(-) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md index 605b270..dd5b206 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md @@ -117,6 +117,7 @@ Data flow highlights: Error handling and resilience: - pterodactylGet() sets per-attempt timeout and connect timeout, retries only on connection errors, sanitizes exceptions, and throws meaningful runtime exceptions for rate limits and non-JSON responses. - Node, server, and location identities must be unique within a snapshot; duplicates and inconsistent relationships fail closed before resource totals are calculated. +- Pagination metadata must reconcile page count, page size, total records, and accumulated records; integer capacity fields are required. - buildClusterSnapshot() catches failures and returns a degraded snapshot with an error flag when Pterodactyl is down or returns 5xx errors. Examples of usage patterns: @@ -234,6 +235,8 @@ Common issues and strategies: - Server errors: 5xx responses are treated as Pterodactyl being unavailable; buildClusterSnapshot() returns a degraded snapshot so consumers can degrade gracefully. - Invalid payloads: Non-JSON responses raise a runtime exception indicating invalid payload; tests validate this behavior. - Duplicate identities: Repeated node, server, or location records are rejected rather than overwritten or double-counted. +- Truncated pages and fractional capacity: Pagination counts must reconcile with all returned records, and resource capacities/limits must be integers. +- Server-index fallback: Used only when the included-server relationship is absent, never when a present relationship is malformed. - Missing node location: getNodeLocation() validates presence of location_id and throws if absent; tests assert the expected exception pattern. Operational tips: @@ -242,8 +245,8 @@ Operational tips: **Section sources** - [ResourceCalculationService.php:157-195](file://Services/ResourceCalculationService.php#L157-L195) -- [ResourceCalculationService.php:454-571](file://Services/ResourceCalculationService.php#L454-L571) -- [ResourceCalculationService.php:421-438](file://Services/ResourceCalculationService.php#L421-L438) +- [ResourceCalculationService.php:487-622](file://Services/ResourceCalculationService.php#L487-L622) +- [ResourceCalculationService.php:426-470](file://Services/ResourceCalculationService.php#L426-L470) - [ResourceCalculationServiceTest.php:53-139](file://tests/Unit/ResourceCalculationServiceTest.php#L53-L139) ## Conclusion diff --git a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md index 3750657..0e4bbce 100644 --- a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md +++ b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md @@ -109,9 +109,9 @@ RCS-->>Caller : Cluster snapshot or degraded snapshot **Diagram sources** - [ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) -- [ResourceCalculationService.php:313-404](file://Services/ResourceCalculationService.php#L313-L404) -- [ResourceCalculationService.php:405-453](file://Services/ResourceCalculationService.php#L405-L453) -- [ResourceCalculationService.php:454-571](file://Services/ResourceCalculationService.php#L454-L571) +- [ResourceCalculationService.php:313-406](file://Services/ResourceCalculationService.php#L313-L406) +- [ResourceCalculationService.php:407-486](file://Services/ResourceCalculationService.php#L407-L486) +- [ResourceCalculationService.php:487-622](file://Services/ResourceCalculationService.php#L487-L622) ## Detailed Component Analysis @@ -135,6 +135,7 @@ Processing logic: - Fetches the location with included nodes and servers in one Pterodactyl request - Groups included servers by node and fetches pending reservations for each node - Rejects duplicate node, server, or location identities instead of overwriting or double-counting upstream records +- Requires integer resource capacities and complete pagination totals/counts; truncated pages and fractional values fail closed - Computes effective totals using overallocation settings - Subtracts allocated and reserved resources to derive available - Aggregates max and totals across nodes @@ -234,7 +235,7 @@ Integration with reservation system: **Section sources** - [ResourceCalculationService.php:359-391](file://Services/ResourceCalculationService.php#L359-L391) - [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) -- [ResourceCalculationService.php:454-571](file://Services/ResourceCalculationService.php#L454-L571) +- [ResourceCalculationService.php:487-622](file://Services/ResourceCalculationService.php#L487-L622) - [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) ### Class diagram @@ -337,6 +338,10 @@ Common issues and how they surface: - Throws a RuntimeException indicating invalid JSON; indicates upstream misconfiguration or proxy issue. - Duplicate or inconsistent identities: - Throws a RuntimeException before availability is calculated so repeated upstream records cannot distort totals. +- Incomplete pagination or non-integral capacity: + - Rejects page counts/totals that do not match returned records and resource values that are not non-negative integers. +- Missing included-server relationship: + - Uses the separately paginated server index only when the relationship is absent; a present but malformed relationship remains a hard failure. - Missing location_id: - getNodeLocation() throws when the node response lacks location_id; indicates malformed upstream data. diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index 559fff1..8dcea68 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -144,7 +144,7 @@ Operational requirements: - Scheduler must be running to execute cleanup and alert checks. - Database must support transactions and pessimistic locking. - Network access to the Pterodactyl Panel API must be allowed from the Paymenter host. -- Node payloads must provide a numeric `cpu_threads` capacity value; missing or malformed node/server capacity fields fail closed instead of advertising unverified capacity. Stock Pterodactyl does not expose this node field. Keep deployment paused until PR #22's explicit local `NodeCapacityPolicy` is rebased onto this reconciliation (or an equivalent trusted capacity source is installed). +- Node payloads must provide an integer `cpu_threads` capacity value; missing, fractional, or malformed node/server capacity fields and incomplete pagination fail closed instead of advertising unverified capacity. Stock Pterodactyl does not expose this node field. Keep deployment paused until PR #22's explicit local `NodeCapacityPolicy` is rebased onto this reconciliation (or an equivalent trusted capacity source is installed). **Section sources** - [DynamicPterodactyl.php:48-75](file://DynamicPterodactyl.php#L48-L75) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index b25b085..9a8c2c4 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -181,6 +181,7 @@ Focus areas: - Error handling for rate limits (429), server errors (5xx), malformed JSON, and connection exceptions with retries. - Cluster snapshot aggregation across locations and nodes, including utilization metrics. - Fail-closed rejection of duplicate node/server identities and inconsistent upstream relationships. +- Page-count/total reconciliation, malformed fallback boundaries, and rejection of fractional capacity values. - Self-exclusion of current reservation token when verifying availability. ```mermaid diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 4044402..7023c1e 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"454-571","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted:6mjqr/IowaZHmZRFDheV40UGsQ0sVJEEfQuKG2umzvjguvQXGNDi1nl747nCkFgOsOds5jYVCKsejZB5Ycp55oXbpBTWUOFuTcbJi+3ZrQm9i4kbql3UWJNNseqDdzVBXYHp7WTzFhQ0U5rqZB4uDZ61rmVX/LpmmgFuevs1x8owCRFo3w/YQxC110zOuoxFXRy2D7RBc6ZTQZk/Reik/DkkqHuXW1aYatf+BkXbpHcpfYrOqk8p9/VEp0mMj0gECCQO0Pqw4Hd/Sv3nADV41c6kckej0v9kJtXhZqOzBdsFT7mLWuylMl+qvHsaHJ0MDt5MzrpvlfrgBeGBF5Midf8ReNZ6ORrydHNfFH09xJE6cpbKTERWFXgTyuay7GSWk5DakToppKb1wHNu0axV5Iq6vDU/uFLj1Nshh92Rdd/Nu1PY5z+2DpuP/55wMgC5+trljToArBiPQOHJAn4PtzRb7TLb+cSeKIxDddZ0ZmkGII9iJGE5gsK+DqnvDEAnbNBlGwbz5SIC+7PUjI6rja91bfQSJVQleSXZt86XHg5MtKJ9EwDGiHfHOD5jfZKwxPWwV/qECGdRIM78OQo5SUuP6twlgFU/UnnGz7dRSHYYeoR5mdmHDNZS+3bThmZbxUgjSht5CiCg+6eaiMcph3vjsDgefJtfFegbIm50KOBcyFp/oS2o3GYLVYHq4Hs2iT2VB/R0b6N36KLn2i6o3cfqgzKAI6QQ1C7jRX+8iREvlX3lBr//FC1VuUjr4iORHHlHGiAYFO50FtKAbrzk9gdnSj/zENTdsp6cR32Pbikqe7VjE7lio3O6NQcNHlypZIcUM+6Kyk+NUxn+LDngSqWYvrLat+AA5GqBFxhmhMrSFE0N3KLrPKC+NdWo99CaBzTZ2A+bbwas+ZajkwtAP4yAR+r8xFyf8kqQJ2tzMX3Hu3fs/ZY5IL1SLOpUeolvQV1APALj4BbcSDmNdJ9+mzDyRnbHeUgoxP7vYaqUQhqO7QQK3q26sySlLGLC/HkuR8NMYBsWaAxDopofmdR1ATxpAKWQyqQW0bGBQOPISzTIroTNSM4RPKIH/wyC2e/stnHcI2UnMoRO741LRUdkDYjkoZ4pX71D5l0fIekJjyJVA9Y7yTKy0s6zBxOnGFh/5As6sWSqEt/KBUXi+w2JtZAsIgHRsuH9UkmJD4i/83YgEIkuaxKNDyiSJc18vS9qZfLAR3k6dIDnCeqx2EUM57Hw2X3lHksgjYxhueVcr9sltsnMjqSvWjTJcGusE+pg+8z8MDo4GUxQt9ZGaUS4ZvT+aMTcjHJXKoT7xs0XgHJMGzLEiKvjeO3Xw0Iys459ym3Ju0jEogWDGsNP+5GSkpYhtX7kVR+zPlQuTlNYPIW9kewpAq+PoPYmy4i2WKlJ01CF7HVyHK73SJ3cASCVTlxVlPoO8faKhwLDgEEmWBNQKMfE4WudF8NSSYf3+qVwzpVlXjK5Ws64YYGZb87dbP7Vc4Mr9KSdsFKOouyOkHfWjwGNOSjiMC/pL5mjRILIh7Lo+fccxeFT4m1nTHIQ5YGG8M5Zs3NJr2dlmf8BEc0G4q9qr9M+lzefp+gykp4fS4zsnw/DGl38T/eqr9Tq+saf9MLlHZE/KI/+soLxPv1McH9P3SeGZCVlvxlGSFoO1Beqn1guVZWP0T5Vvs0GDZhcb7HqkmxidrJAMfVnTde6+UT5awe/iqtB8M95DigmGKah/I9I4gqTYGRnHLI4C9AQR3yxlke54c1/hifk7Xj5XKrUXEKBxfyF3P3TY7GUMmtndNA9a06sonBYWM2kytc0U4e0AvSuPhJeEWoR7QGZqo0c9bdkhlRsV65XFj640N9n12eEBa4G96+SXbKVqj+zKeECjLiyMCKx3wDLHa9Cs0VK3KIcl3heMF6lMIzAZOKESrs1ltPN6CT3AV6bSp3F2jT/46EQw9KJYDDUJKdunvmZdpah00g56m20GiY4Jg/7g6Ka46DENUcU62j4muR/DrcMxA1hEfrzTjcGp+f2pze2z9WX5Mv7gC5W90ozOfEvK1HTP6Tc0JqLRj2U2DN5Q+PRfNMoiI2JhfhQm9Chbqmoc86RL3z1A7N88M6VPqamzyPLwzMBXt40Dh9qsi1tNVwA/s9TP1Q7fT3IOCOoclDAbadPOKQMQLHAwas2/1sFNyfDGBSuahQ0LtNbs5oNRHBkhLr+2DFiaeU8SSo9hDAKRzxUiCOiHNFt2XRd4c7zs46e9mJCd+pGIIDEDKKTDfD+Mi5vpVMSivc0q3OW8GuKSYqbVKEG+Gz9HxnmcGOrDcJkRrCulqicsKScSX5/6bWoCabWYIGTsC3KZSueEu7f7xbsyeocxHcOCtU7L5evb6lwfNaaboCWcTVtQK//aet0C70B28WMA9Wly02VeyiGD/RGYWCM7Cqhw9cn63O9UPBKpaoCza2BErOXWtOd9BYJrCahN1jzCfWhDWWquHd+SixiIg/ApExEl7LhfWDhH/yc1kc8K7hq9OlD7gzfJICamZcYrkjZRBx7LebsiA/vdOcyNxDVW7TZ8H9IaAhsuynHN+8hOIBpem1R6ASKkuJLZVzPtPr6nWvHE3Xekh2VLXKhZNd2vN630Zn1KLTKx3mieZk+Ojpa0oXplkte1QA8UDEBLVAXkhbuF9011k2Bd49V0BvMoFT4TDLVJtZ5vQODFyo0C6P3yUpxBKiIYN+DjDuGENy3jZcIQYXIodgg5b0jgVGTMS5uWJSRewUjx/UgZNmbCq6LibeowRk2JiqL4DmiKay2mkQa6BlLFyhjYwWTHddGNj3NrON+35+AN4dpdCkkCr2/kMPv5mnzgi3QJIqWUJXUHdUg3ZbQmG/yf58hLn3J1bLayAu4pSI5cMd7iDOcPx5j5+QzQSAVo5X3Oa1xmq6jiDh6/AAASkH16Hv0sASVxuE8TRWQFm88YShX/aUQcTgte0tD1b0EpuAAceN496lJMmSVM5izotMtraTUMIND3ytV+Q+nXF7PiN7N5HUD6At5Xg32nwCbQ4vF3nhQjOt5820Pem4fG82RyiZw9U3SA+uxVhaXcdV+WCG6wUh/15yTOBbdvgKt9pSm5uYioEumFQOHq76xkVgDmqmFo+4u5k+LUq/PUjYSFBiJ53/t+xu7lz3ZC4pCsqVO0cFPHust3mBOod8pBAh01dCPkD3oYfwnWBPf+MbnhO79AzA6UsP9Bfi0KOv/yLrgVXRaVMZGw2C62K+4pLxQkV0oaX4D07sVGZWTtlGn/BOFvX/MyM+17PAYd4OaEvl5gk25vy5cdm0PbYUX3DZFob/92IDZe6wXDqzc0rAIXRjCOLcabHIKGvMG3BV188kWylEKAzIJpvHKecNawEBwR2xNjR+fMAZ40sNzLD0vMxQhWgC+pQT4EiC7GgCmQBssy18L3QxWYnhjfws4CmhpeLRMk3PwCLNGw+p4xpa3v+G+mLeNlv0FABA4mYmEeOYhqSCfB+jFw4Chi5+72zUGzapammzIh/0GwNYA+WaA+q4z6atxIjj1r17hOM+jO7RGdcJjHxLcFMujfG3Vw0qpmqLO7CCVTvKxkDgMo7lTLTDhRB2nn6bYw27Sg4/SMcy00PIQ9UyIGzhoJIFDTGp+GnFCVqjbknucTfn88utRVQrKT3iOdSHV6G2r0i4byvp1nOtfK06l2mzCE4kVP5Nm2KuYSotlAGrKZPezokOOmWQSJhguOKILjeAYu6lf4MttjIF5ySTVpJ5CsWXs+bZY3pKN2KS3xY2hZtXmxM41S0cfnQJXH0ydWGsbBNLIwVhaha/boR9zi1owv6qWynnFkuASutH+VJtgoqYtge42bGIm8IiVlmfB3Z2q7kNchPgFPm7kfIALte/FLswFb6GL8hLW9O4pEG10vRWPrMkxu/5Cm0dM92QSW1njxOEYj0jHEwr37ZBVJKE2P5om2/9rjYU6CZg4MTD1ybE/t7Gquwnb9x8wm3NdsR3fhVPKOlJBh/XA7PYCDy20HtVSmvStbm0pho/HUmEVfyGQIrgbMTb6IAhumAKWb7NVkMkMhQZjbmXa0Wf0cAyZCwBLBY7AnwFuQ9niRrsjpQAeqGZWtyK2OE31WezwkpoR/X7U7IvsmnR1FvIGZAkKLIph00z7YguWain7pmC675sboI6TmC6XiI8mizzm6xi4F9tXE24+8LAF5Ff7Om4mSZgtyFVbDyTUKKIqXB8UftRmbUbf7sUnl73HsMrl1R+AB9rqOKvgQax9ip3OXwVGFcoPRMwqRlFLoFJ5TkW3FqTCrdC5mVDMAAXNvxHJiBL04K+0pyV5wZ9twfdJhZVR+OfNsUckWFf8MVuWsG7gtuzYCPSbUJjWiK6e2NtzdQTrWyOgpTUkoTqmrNofApyekFDaxJn0tjYeU3sPXMbvb9w+PA7j/l8qkplDfNiEnWRjljtOktshJHGeRYRIKpKcxWV+1iguw+czhG49VFPQRgK9xrtRjCsr5n7tAGJlO1VlJCEa2gOE6IW/Bco3YysRsVBI3dedsoFSVfs9DwTcTNIW4VqaT4MN5EtmVeA65cvfoHpiNQ6ef+ax2AVulUiXFFDmP7yDVMursb0FcXm7KIeDlFC8FRpMa91fp6nc14RrzF441OIyya4T5vbotuokwULzEP695MxWEBHhR64MIZjRScsp8oQKonpHbIec9spVDYiN1HaQW23HAq9bumrRlFiHH6nEKV3H9pXLfVsCtknfLhm9c8JyP4Dx0dFCxJB7Y3v1J6I0QOtj7wb6hrYcGl1+3cBPJyon0gk51eAspwzeHLHiuiEpuQnoNL+1fL3Z40orysvlX1cvpMol9bdmlE4XgbIXVf7KSJL3zI/FkUdoQUqLmYsVs/g5ZpQwrMz3aewxCAl5uOw6sPHhs2NYlYwrdwyGE+zUkDCyf3BssHA4/crZP47IQOnRufr7ZFa90o4IyCJ5wthw+T+c+h0VGeaNnhdRNp/TyQ5HNR4/qN9EdxO7tr1aJfF56hummn7yaTxsI5mIbmJi8uOKGTJU7RHiGIsWukchtx3HEwYBDfNbetAxcQo+1CLHmqs9tp7PF24BP6Qd7BS0nrdRz3nZJlb8cdJygLpDPj/4rh7HmB0e0EOg/2RUUUnRE0ZIZHRuJD2gXv0ZFEF3qIfgXW8XFjplaEnkihIdcnbhR9dl+ZlSB+bABD8w6q20smj/bBz1r4PaMsgnA4UIzHMLWV54yX07E11atWtmN9tiTovj1xuuqAwT3tNr0ZCcJz/2mi7DLYwAem/DKExh3hab4BtDKEWfkghoJZCJPwHQkuc1m6tABgoIs3hqQNfBKJDMINEMnpnvlD/C2ol3Mawo7EbdicIiGsc+poqrky3tLrEtZoOZ/zft6lb8pQM/mNvX6ij6oYH7lYvdtSASOmlkqtuSKyWRxlAASZVociul3HU1q9Xt68iDOvls+aFS+Op14OcvKzqpOTbW/6gZizQkohhXlujGKecvQ+V+WAnLEDgk0W2cA0Mlqt9A1A0HPHt/CND4J2LJm4AulxA+sfXYEmSv861YyYq9VaD0tq6p1LVpwQ3cm5HjWcv1idt8807Z1L2Id7ER/N7uOUS7L0k2UniL7P6QC4IEJW4JVHvQJaO/7Xc7DeUIkv1SiBiGVzrardAiMAI6hSafaWZwAvwsn5GfU5Ng9Uz6JoGf+I1rHgZwb6PP9YAkFUXlFFBqX6CQQt+9axTPKKd/AZ9w6IHHIRIXwjRnLupSoiV7JvgrpQNcQoY0LHxAF3lTlBd91gKvbwWAYTiv0QdBTgJTV9Uuc4Zdp9R9vNTtfs6OpInFvQc0bmKZXoTF9P6+iUetATQfRshlgx4BjtfK9khPcDSsCG9336Lptz40AUh4nmPzxXNZKI+nTfkGoGCIfqVvoUxwlgzFVyngSIll0RlNPMaejUabKI2uvLdBDmnVZLtvK6fW1OxjXHhhSdWwFjxv+favZ2y+suXte26AmFOIuyv2Rm6L9ir76htUVDmawHsczq4PJUZG4OtD8D4JKgGzX7Vg9n8EZGBGykh29VRFkV1oHR3DYTHuldeBQ3z/lyBRB8t39OWaqRQ7IrLD/0ZyLn1bB2ZvtTo6MvW6yLb/ckvkMvQXe9noPrpbHHnEHWnrrCtbVeWWOsMVBYjUgFKLJzeRxYUk+vibIKEz3a4/fTxll10kOIsOjIp+x/dchyU+lezTz0W2esT9pfc5mnIachMdOYDqlP31+OUrIYYX89P2cd/u+mDIPf4F5hR61WWUI4dKHEp+fRgRCOrUk84LW7kezK3W0B7ri1r25kF/2k7gwkEVBL21zmLXYXNFCMCBJCMc3iVDvKYCktLPUOyCheO63oRVbGCgL4LgDKP3gObuwT9xTUDZ+L/cjdbykPSbOBQdrCTWM81gq1n13ehk/T1jPoepjUGMToGvfbBfhAtXvDpgs1ly36iHB7ZxZCG/6n5PgFzjk4szJqH7QfHijwW9sJ3t388W/npXzXYu56ESyau3yVwRhKJ7xqT/E7woImUiwkRE4kwg4tk3eQp415DIsAgkSCyNqTooX9T2udnd+708V8Nwl/B4zXLGzOJQG8QrVfiuYEqRLReD057NhtQ/D/T2U7KGLAM8cWMC0JeVQgn+/tS0CcEhxWwBmVwIp7zLbkWqezjc35Z7mcRepBKS1Db1iTdM7YQdlkj+XP8me5+SHNzzCdfhpNvKMSsvFAFiIJeUU087OD/wEnMh3V6Ki8NXl5sYeVWm4qi09QNYPFgl0z/3eU4K0k3i9lOsGUuBSm6wP+0YTT2ppve5AmA6ioi+d1dbPZLnVAISA+LT8ObdTeW6T0wYbwM4bg/qQ6dOzsKfDpLmyfcYWmNS2FArFhua1s66ZIXGObc1IcvwdHU6gPWdFnkWGSTk7DwNJUyQXooUrNkYL+x8tx14/kOznj4nFBfaT9KQiiMNZVNbSb7I7HjynQG5I1rnPr52Q+yhJOXPMoEaRwDpe4pi0zTMNNEZMmcFWLa8KQi1A4wkCerMyvQhgf1WyJqOX9O36SaJZZxEdG13f3+PvtJNFvMn6iJKnJ1JuyadrAnOVwx/KaNbyNy0DuVmzeh0maLdTIy1yY3d1a77XlcNIZDAC6dAS4V3pVYogzBBRD6FP9kyMpQK22LJcijv2JCyS92gCJbAiR2wRCOYf1jImPbeDOFLCGK2DDLihrdSWMPXzx46qJ38IF0UuGxosv0tL7iZt4TrOXZQXtckkMCNZpLYgH65d4PXF9s4NRA00KmfLdh0z9ihpggvqjkXWQCMsef5c8jBivY/+e+xx1XY+7pf5zBbqi6+MmGvkRnhbmLhOcyJ/bqnVfXcLcrmMUoZtMk6m6yD6kLYau8zhrwR3ZdIQwQ7N3WfMbIo8hd2FekMVIDz4cVfzGtEkQSPIIjmJeUMZ2TsfM9jyzXkUMPKetiALE7UtWxfQ6eEYPOWLNjzbh0sGp+EUoB+6OvP/1RZzDvAncgz/nWjIAS8H2S4LrQTO34s5LGGZmDLRl9f/fVVrwfiWBAeiD0kBXSYTNeJW4wULnzSWlvYr3ll9lCaWdQOnS14yJFEW05VafnYQ3UM+tlbJlFozQ1zehZxNc2Pv3KF4yFp0r8o0fYtMkMnvA8Xh9dmvJ8A/tt7GImE7fvCZKxANwej9Raaf0eCwLZfdW3lS7FB+CZ9y48kXntYMU9JxFUnqoVQrF+hVMBjMRR0abCVXfOVAwbxvdAxIrY8qV+jVGa90WvhAkKkgh+Hf8yCiri6+ifiMfDnv+k1W0UAwQj0dLPop8z3y09Pn8A9G80BEPFmI91s9HJBsAPXccTYveHQktvoUk7Qq+W8b0dAsjsQFs8BcTvGwvQFCYvLo22JMgHL54hZvcvvC1M6sc8uDfzPiQAj6orQhe60GhvE+35362Atxb/fCtBAaKGebYAAMRFg+wsfAH4aEzHvhSFVl42JGPakQS7s2bTx0cbVnMLsBSSji47jIXqAXtiduTFP36loKpYOl7n3KmR7bLcewC7AeNctVIIQ+0JeM+5FjJEQ1EgYA/Ax7GmC+hdXezes3eKI1c6dMOjX6/3lF00DjU4+AvhBkrR3M3ZJAWqr9pSB9fy8vmQRanQxj0Eln4SKNu8IaZ4WbqlEEmbOFJ6u4Io0RSvKzklYMzlm38bNqqEckKRNGspPs7uqYvFfqG2HmzKtzJVJuKvj5zInVSXD98FHeTFA4Eg2qwYhb2H76Pqdb9GFOMODMHna5A7uU7jrSMKTK0goNnv7UZAPSYdWdAEE0E4kHh/F1Jo3J3tOfqXI4ELr9skT6zKbOl6YDbPFDMgUF0IhgO9zQhKrNTf78qxC1KK+lA8KRdFFQb+PWgT72S+ME8dufBZYKNvbhX/QlkgrDm2qmwIU50VKz8MCXCQnYEmjp6jiyqd1FmZyyMg9N0AXgHaPAQwzWAmB/G/YJOGjmk7g1+eu/m1GCOljgkooweAOnryPDQEBmgcG9T1ps5P6ps+Ya6uiU7TdbZYgAZVI6oxeFIPYeGtMqCiMkwDcmWEfYlp16lFc4lVrhpE3wMtXl8/h3UsrNcY4jHEnsWf5L7wV3ukaj722ZjoQOkGAFIRiMyY8F0CshW44gtLgWetKFAlJ9ISdV6GOFb91ONxkUbRHNoWthbRayDDBOixZIi/5w9LMwGSfxfCyzYlnGgBvxxZS/POsYb9WjAVOgYqj1+gA65EpkINO5PzzG35AF+ti3s4QqSQWtuW6ZW3Ry6uThtt/Tw0EDlFDUIXd5K/o3/U6EYl94tslMYDc+AIoEWRTkqTsbsm6ZlJwQ7ARR6pJNWX9/7NbE9VjDXFhhVJwnKWCg9dTi5ifCRMW9eH0ek0hg8fwYi8daC3JoJHxhyo1nWT1HdxY7Q+UxdvBh84hlvXvwD/pA8mD9/NYSVJ2n1O0PVGMC6oQuA2SFQ19/+z04TkDQEi1x4uI3PvE7w3kRn3kfev7JrSJ7508vfEPT3MylzWYGnNNjlstjJpkubu5BRDzKC+nZwylJhJUhrhGCH+SfNH25r59CTULN9buN3C9ZB7Ea+gsFvnZ1TeRDY5tzP5u4RzCkrUlC9uhhd/y2BXjMzZD1xwL3FCXMECHccdnKFfpjbUrhqVFJ3RubK1osuMzNHQ6WR7Dy11GLbvEXA0F84yos72fYJQxYgjUb7w97j50wmnnL8DXDXrQzFxX8Ahwa6PtHwRH8FyCcnvqmH92eCU6JUf92bp3O8J8WKGBO+pfvcFSCpvtZhRpvbMlaus5d3Or7b5YmFqk8ROVqDqFPIEhb6dyDQsdzrs/N+X0hwLCg9cDxpb5r7JOg24OBgqtQOPsOCK6rMj/b7dmPIbmaI2su0QMeNCO0wUpim2/7GiVNgmq3I2Jlwg6ZlhZyz03TiGygZc3nLzdH75C0zPglSVXojAWCJps2cIHUozW/0ivvt22v9+WwcHMnMUfj1GGWs69rtru7urW3Xz0bcX5sAkftMgsB05YdWZJhZkMiCldJMkGfvhUo61x2DRig0p9+WhKv0TUTqABK+WAbT4yjgJUS3dTGFpOGqmWZZRVD6xXEFCsRg0mSDubYcSU2YoPE4k0676dXLj7L75BGaAskadGF7n2eAxJ286S28xa9vm4yVZDYlTZae8eI+3pFTCbFevS5J0kGdZ0TSzy1NclOpOPt7vnT3LzBEYjxjILS6xFmg5+WXnGyAW8YDip0bSslLGkRd7SaolhkcCDz6r0s7gZjFtQbqdScI4odDP1JEweS7TSw+40K71Au698JTMvI8WnIcowhu2blG2b/kOQfGGlaUUNZoVnWNw1IofA8mCYAPSNwPhMsKyBPaKPvY5KAgCAIfHBnyJyXwOXRQs9Sdld6+LtQcuIBv/zeHlF6w3xZxlGbiC6G7Hb2Wo2TJfUJ4tACJnONM8BpETTzFtptGgNipolfvjb1+vNsWAByCkv60yOBlFQcAUzVu0ZZzSGNTSYEqgd5gYtqRNOjXpAIZTxw77wIkfH319Ud1LdZmh29ynRBprzEWjUOi66Q1dRoLIDK7pVsItHaDTmvv4ZnSQNhYqyifgnpqZLRzG84/vlPwipBkOlO4L+r1zpZvvqY92xyhoPnL+ODrrFvaKqI4aHdJBIQdMGJecD9t28ZLhkGuUG2QNpIp74uD8eJUu4qAB8FapCHd+kbaQnXlH6MzzinR7wrcgWB2ONA3E8vPjzmZhiaqi7ZFfm8M8AdVWOdxZYhzBWtK+/CiL/7AO9cOQx7tzl8BNb0hK51P6PZrfnitbvLw6FIRv9x5Wdr3eITxCLOm4hjKr+yKGSG+wilmAejJw5I+eFZSNQ5vYrITiICkpFodOC8V5F5EqeosnDvQIcSs5OeR2AC8bPxWjB6xi39ET96Txz7UUC/NxihI0SZBMmVd4S0ks/kb0RDR85/T2bnlGsRfaxa1LYBKkjGMgw0SwWAuqRoJltDK5RIFKEFdlh5tSmsA1Or8T+PDd59CfOee3S7N2twMQLZnTyZMafxdcmP67y4oPZezP7Bnt+wNqF134fyckNDfmXkBRucAW/OuhZS0NkA+3nOdCBq11LlDoTWgy1OW2ljr9/HbAv4VqJJ0YmqdOjBc3mEP7kOcB56VkzZG4TbgUBxSFn4YzDMDI26MAik4zLCiJHTUKonEQ9tvp62qqO1nXIt7zV3l/4cyzyhTQlcFkXV8PjKBYH4qTUz6Nbxao3h6J+WmfKTZ+IvYGl4VxKteJJTpPSv+QWNgqqgVavZW8XsHZzukUB5IRZ7/H4Df7ABQxoj0LzBzE/75ePugTJuzKFQaVHn43L+NVo0ccFQkC9kTiNg/vzAhRVtslEXSKwneKpm1pIeZWNdZhccTrQ9gLciXENj/W2H3GfvMv1vHIoeBKqaOSOgrx9ThjiQuKex3s1U/lBBC2ke1euyeRJ8M8K30fbY9I71fAAIYV6CDK+FZIWroAss2pHFYpkIfIyZCdc0LV5X9xUrLVHCLx842ip9FbyCj+jw8zr8AqG2Ad/1H1veTeRDo81gktDHY/1cLWgncmuueupisWDTjod7wbnFF73prWdsWJbBh2FyKAsupPUIi04tiV5Xi9LZynAf6Aejt6IP1vKpqkqg0mgIXPWx11JD3Ck39iPElppAzPlUklgCH5CtoacG7KTzrVJD60VLALKPCaJGXoX0vBl4z0sNzbx3JWrW2bZPLRez4J4EK15PpJ/5TmsuTQy28NivG9ljUB2KMQXO9WcDdvZ1/VqFaBb/OwhtDdHPkQAFOYe7uW/fgTeTFgHx/NCnzEMzx7B79UHiabsHDdBAxTNLophWX+5tUfY7qxLweL9hxSq4+hVt5/QUzKmhVvz4UD2Lx1FRAJS1EOdUrSmmso6Q7jklo0e7sGZEwKSxUEF2KCXXb0r8qTjUExpQqdONtE/aU28jpqehsHk7XRhPE2dYPS03q/Gm+T85nLBc2cyQ0TYYx2Ejj4GqXeNjXkWc3mZ192ZsOxyh3ucq/9d3JvR+SzMdS4HKPyju0YbeK+mX+NFm6bnrRakiOM9nZsEUs8c2SPX+70lMzaPBEWNpfFrBVPtWxqRSSpT6Jce4C7L5jJeGfT1+lCSooYRKNgsNeifaQDgPs1vb/Mu3xRMP1ZvqSKtFRYm50eguxyYzvg/VeWunsvTn7csVEAUQEfRj1dcLokLmWk0gYX4fN6ftixM255HXKIHjfx23S+lW1gGSz7SAVuR86ew7fmwDY6u1R2vqRBEM9g2Ualy96gx6GZbgQ2v5/y6/aGLCTAWSNwZaUHNihS0KggKyqQP6fK2PZbaCiiKmzWbhsGjOVoRM9j/VFlyHdgFYoGIoRjfU19PCjZhnCmm7Lk8XhReADCMZXrUvlvNbe0JCzGPGoYTn0HFVVCoXM/7LxASiRghqIjmF4OWqLVFTQ3sc1pBbRo5BsDcJFIKf7G4laq5a8EpMO6jKX0/rXx2RJKUIaRlHGUkSPX48tuOsFNrpgwozw/TE+xSl03ZU+vLHctHLwXEcojbuB9PAt4K+CSZu/zzbYsA86LUH9p+tc4Xzgn6bX8Ztl+iT1zmrGKh/RWDjZ2tJiLPEThKC+ihW+D2AXn/I0SLTFmddJhnc+TLBlPUJl1G4q+F62bhYZH3aJJx5YiOllGpu+/C9GsjN/D+b0pT6V20p0F6sb2bwhhxl9aV+yoL+O4zJIO9FQv+HI6nz3qXdSZt/lZVltoYmw/mCKmyA0Ka140Y1WH4gTTG7nU+Q1FM/gIxRy3ncptjOYZvQfLhYoFv7Avt6o5zzxHoti9VqMt9j410SHYVKQefZMCnY57FmI0yE0bt56TwrXs2IUUFQ83P9kmjP4/AAgjeC8chzIR6x08UjsUvv1z+PMD490ZDWEI6ThAWTAlJB0xMWzL49F25B6HTtdwj3EsByLbjiZnXwhB0wnoiC408/ho1QEpk2QkrtOkiAf3kKJqgHjRtv4UQ6WwhoqkAq7xLRlTKtvtfm87JM0xQJ3XT/72BaS0fdusbwFPXolosfpeHFLqtDMsWPYb7QVDJI6+wtB7DG4FSlRfqQXCH5IkKnlZxTgap2Qd1EFG9cHkivPVMNgdhaKX5Ek30p+65qzPwrQsRtpMjk1bjqL5sH5yZMIF10GJIgajMshf5qx6SlMAdjB5o3t9HK0oZCfBk10eEXXlCXhOCyMYjtQFl/dk7OwJU1oR3olm168FhFz0DPGiyuoLYZ5ZZYVJTh8YShowibINrW+uyztaFNCnVC2orjpOMEnEUeQw0JD7LkQwG5XLYBRXZugCSZm4Qftmpq4FBPgXGjqEmriNDK3chpxHADXSdYnW5NmEp82CvWti+YU1wCyGWA2MEHu7wE7lIiF6wLKBvIs479hJrOISPOQpl0p1SoE7rIOmGmVFMhBljW/l+/d0oTWVcGYkltEPHoScYsdDBgN+sHWnjkat1Z1yNkqOA/U7J3dPfL9vM8NSbiz7vCOnRgcNtjJitxkbYZGXy4WbbCwFFP30v6+fc9tPM99l5Nz2z4EfHwcQnUv91eNXox3LsnzaW3fSED/PhetXI3hkU0kWkPezG4ZkuIdriEuhuHiKjgDTmBQWXno9TDxkQj/aUql09QJa5N1UPmce53Y5uXqanGG4SGyQ9s+epdT5Vigc6Q1lC+i6ZeBTlij3vT4575jFkIqv8d/1X/XWoBEgtqrZP6eLSaYLo+r3Wr87hzRP39q05HUQ3fkt+00HmT9QC7h2rEMxR5ZWt1pGJSgcPZqcVgvsxPUTxtxqom+uv5Z6gODyOjG5CSlQY0ALfBz6JsPhAE/q+YTsCtTSMmz6Uy0R/Coyoeht4nqagfm/FoqfC7dG9qtc+FY3LTC2r3mjNHS6ar4QIynNPF1j9S1HQAqhJDBqcXRk0iH9XTlXq/0p8AkdDhQ35Eb421xJpgcVkTgBAl8fn7ZwDhc7zy4QXVXitL2x2wDhbbEfLvUKO0DsfA3pq/uCQJc+FiUGKWuVyItZHmSFmrPXHsO2xc/X5l35qbJIM+4iyfCizhRmufFsQwoA/kIyp4+nVNmtQXZ3J1P+NAaEFf6u046uNTxVxwVFEkaAkYPhGGI0aWnxId62Z3nJFDgwg+E9AlW1iWAvJewOIPwqSrfl59ZWxProiUO0htNns68hZCiDI466Phqw3p6GsAZ+8vHk+4EIHpmXm6QiqY+OrGHFB9d0YWBEGOvWfoBi2Ly0Hy2ftH4NoxTYJJx3TgmtgvG22xBaLAzd206yBcV2rfs72Q60U4LKl2nRojE5LnUXJNNDBfGp1RjaTmtPyGwMJk4WhMZilTf8mrjktyde404TJGSP2mtMchTyMdJFfZvqpMrfnfMsuQw1sYVfJPa9aij/dGVaxMqrGJxdPVxIeuYVMofV3hweFVrAZWJVdu5SrrRRbAAgF1mnAcrZ8qjOcftMA5VuCupRV81hZLIryA9Wmw9RcXumv9NR1LqGCQjc9l/OP+a5n85XkUxGY4YqdVQE5Fn9y7KHU3o5REsgBxf9spOWTo0BiX8Z7QjDNcKlIbFbJCGVwtRLZyIUpuGknCjh/fzQqpaJQT37pCFmmAtmULb0Nnj6bnGxLjs68r1y5UWadqmIRbB5HZ7oljRYo1bXKOMKRtgwYXS9LFEppyQzwbiR974QZWRqdIEs9wfx6nQLashFS6tG14v5s3FV/fTFmnczwwOq6sJb+4ZGYDJtYVPwSWtYJvEWaG3fGUz4GdeZPajnoULvy8QQnlCCqT8Bkmxsp8zpGwzoNbBGsw7NfU+1HvOm/KVkn/rVbeejpKvx+QfqzvtUsoi3atH3eowS+DZ5GcPfQfSSgREqv4GntJt4Kp3jd3Wjn7mTBYXF2sAJKTROvumsBiEkZu2EIsA38Fc3Ui2GwELKHoSAyp+0JY7rWJB1TQ3yxcOqKlkpZNIWQBfg7mgLfrmHeJ09fQMRomFjfHTXDQ/X6C3oyUwWiPeFNh6ePrS81SP5FzlomMahrmEbirk6yIggnI8TZZsXOvMvs2IdwFV0wFr86Vw1Z7az+dg9X6SAm29aCCK/JsBTN6NF8g3FekeUGYZFIQ/0Q6BMGhCKSFFBxW3AkhZE0Rj4IarQG7Wpnss/As/IPYOq6LyZVpAAKg9R1ihA5xN9Rxv62yoh6StTU3YoG40rvyVUm1jvmR6d8maXUMN8H2RwbA2zrVVhy0ZDqxIIi7zloZVE7TmjiSht2Fz+zVb2+5uUvoB3EnmzCIAtmYPDYtWBuRL8ymFbPX0GmEjNGEnokfOdKcUiI51QTmrLUnp0rf4r91ispSQjeRi15vBCff5qf2zZNVHjfjZQBidMAauaXpijbhdnj59faJnyrfWITXhGFcQiwqYbgfc7NRAKbUYklqOtXMb2n3L/oiCgJuY94RwyWOlY4w5McWksQTppOPG2jME+/pyljRUNIWHMmOVJaf/ysT6suX1kYEZRgQp7KR0yAsE+iQFaEjYY7FlmSsYxSYlNzElzA7gs4eQ7x6tCBB2pbxss03SJl56Eq7rFOsBfGlWMsN/8afazppu5MS0oJTKvcGshtzJhfRqbfxoemD/a1KK4KE2jb0TUnA7yeVCLJcUB4DLAUC3nxhusw3K5TdBOV+Cm5s1+YTuGPncGlzjd0UREp6UNtzWBWN9DdFKHfwqUv8+TGysrlxBFYXCefqXqDfePM1/Bw4fPLeiKaHaJoQOt5LJMZxUGYuBlXAmOxGhDIBrOdN/GKOgo/kIM5Qo2HS25WmIZ3Wcn9EimR07RUXBxEs+I7J7Nw1uBvpzjGtItCNrZXCxf9Am4OEvzKYarWW4DUdLWqzUWEjfxaGdkFo0KRzYH7aHi5paFIjned2xSh7xs7AIknGVNj008ao/hdwrgEOWNXixJtjnYVYTWhxKxcdxyBzehvUtl5nohfhpBzPqRwg7DVRr+mGtj6zI8Db9F03oaGi+vBgg6UHs3SWEcCJ+impg/QGlKERraKegmgdc0oe/HEbOjvly6uMWRUoKjkbZGpnDmuuOFKwLBBSTV2GIvbgLpOP3kgbChkTRgBJXvbqo9e5rmlEfRCA/qJLjHN/qYkSdZfXPG6FL4WswFMQQJfvmrb4aweoVjdUjWDcY9oJeIJIPbRcxOMKwODZ/EmV1gCJxwvjNd9lH2ZRjNRuctdnOh1CFuj3xWAbz80cmF9VfgoDfM/3eLF881BqEu7CqCzsmEc0zvId/Hoaw7+d1WoIVnnZFMqLYiHxyRLrokfFDl4gVP0VA+f8ibJdOxkH7yfFL1pPEE4/g4zTrCLjVoipRKlRgNtrIHMPO9YVP8bKRqUXfZYvVnEvAeJwSewWNY06x2jVaiXp+R+q8wutKccXdsQR+TdzKKRBKKEtVIlRPI9/q7lUt85SNYj16kxxOWd0JusMpkGJOz7ji3SD2z2KwSRSIfOhc0tQFb0+6d39ymPg6ZXLOFRtt2FXxLoVCCpG6fD+mzD6ciln0PbMuG0T60Ak9Q5fFy5N5YquQoMf9r50XJ6EDhBMudNVHXSc3a0ihAvJni77q18MCtKKwSxk0V4SHyKR9WTQQ9IYleFG+MxZ/vUT1G+F008jQW2fo0y38YMDlN0EuXsXGalBDZf3Yrtb1ONBjLoGNiDj5rK6L/w/mN6XTwqyx+Ya5U2GmLMQtnsraE9OjDCPciksyyWr2jzYIcE01m4omTJVX7tdtpMbnus5ibBFDboryjPK8wejiv3RP7aUuHIFg19r7wHqkUIb9XPKBfAKnMyRD3965yewX4ZGgQJ0It8bjWaRVQmhNao4v6or2A1wLyIm5SGEzkXZUu/g7yCEhxPov5d4lBM/IGPHVI7c+tr5c8ABK1XqX+nFdSFyVSaLF6juDWqkyEPYmil/gsMFYUf0hTy4mRK2wK9I7Zj5rmpJN1a8PKrg9N2Q0jskrogtFO+3qafrCEy7LpPI6/I6kSwhGNVQh2tr0inHRw7PgbKY0Wq6ySPcTv/And0ArWq/fxJPngfosoRzdgbmkt3NHzw35SIXZjb6bYyGrXkNA9KS9axVNkiWOODA2yEEwKxrbd7UAVDAzGZOROnFc6zsLHV5HNo0Bx8h8w+Bw8uje8fAyF3JsWzuSXb1yZESI3W6eTLzpovZABB1LUQ5e/7oV+f78p6isaCUOHQRrdSFuvNGUrX6NaHfzfngyafHtokm+WmDoYXlqyeweYD8gQlvRd+q7JJZhFGwrrai0y93w0RLKMQXX40+Pe0WSKtIyoiP0TnDCvuf4WKzGIK+r4QE4BcmXLO30g/anlURkFY0BT6dpB6L4KHgngD32Z2N4UptS1G9g6fC5EShjGv7SiPgoE1v8rrnrLpphaAGvtO1VPowvBdPEUsAI6jzAv66Fm2F25ZATwUMm6N8zy/42lWISydAOxhmaUxCNaow2cSntwWRFeEy29cFbeG6y4hgMgGGWY7tAg3xZcYFgEV4k0XPx3QG6ogUdty5qLGD1wNbtkTHjN/bHZM4axMZCVH2pqruKLtZUE4OtKMho0f9K5fXMnvpnZAH0/Q9DEoflsAaqcGTxL0JcO2lvNEZWHb54m/JpwDrKxQHVLrJ+Arvw1S+TZp795Cqou8SvyKEJ1iY6qOwa26d8h5IMQmGejTRZnr4rp7zbbmyhC0swljYd5ACkuZdyjmtmC6QdrrmK4DH90kUEwov5jJgdYEroiCiQXEsGZ+giYEOeM3oAdmU7r0tx4ljcZ92PQwR97hV9ICAbCaVV7Jn09Qq8oa09FCdsLJ1v3mgyReYhzVNrqJK7vSSZzKS9dPuBqoVyqk7/cH+Qon17hgWuTSz/N6dX2bbOYxAWJ5EVci9y4s29cclYBQqeq69saS4SeSqEbCMfCedhyZkwaCCXczV7qJeiwMb0ow6CAU2Hx7AQaDbiwGzK8mnnGpWn7lJQ2VVGn1QQRz8+ffpHDj2v35ziPMbxlfJEcqnBjVlns6MnBEPC1ZqmAvvz9Ec+EzGOi55nMP4KR8CM/EBVEYVrDATJtqjtrkV3TuTZg9huTfrBoC1l7kdwIzJ80cAkhm+HnB/MwFwNguxAfSIkbv/vHRo8ReiMOUzGIe1+K8bRygvT9KhVwfWTLU/atlZgA2tANnw6kJHJxBAqJF87Slcn49t0ZZ7xXOT/LqbZ6kv0y+o/vnmDfjqKMrAiftl5EGNY18RY3P7forhR9ZIMMK8pjFyJyfOW8BbsTh8FtzJvP7/JFPb+dkD1/7lvL3OXVp+OLbDwAB6W6+5lFA4wy8PRYlZafepKf4YW/pXMflKjQAC7TOyVyYFmudGSmJRW2sSJR1CQxqbZxIHor0QJo3YeyqdscaBNGpi9M9lRSMw3Vx6Pbly9Dj+6tTqRsnmKZRZ8XE3HjaEiOmkU0bvKH2BE382uvQj7vWCcHzSOpsE4/R81It2KzizfmSGwTs4MikPF9AQHRkt8kcfeoCXhQKdd6iIWnOtXAngEYy9Q+Xzs+bZkr85Y7nYq6vfgSDKVYJzG/zmUJL8yZVl08p85ZWgvj8wyupegXez6PCmPdDHOVkOcywmNwFtxjxmVP4QU9IKX9/D9W6CpMRUeBSRKMjWuTmjcI3pLQgOIHDMQ4PDZ6wV9cDlxWLIFJXbFPDNtjqMADR9FV5XOCqrih4jZJ46p/qw+t3SoMsoNJ2LplJOfzReKR+IwKAylNMbp5t6evIOYpk9QBF9/2fdL2AQvJ6CPJEuWQcIEhObcyrzSWnklQtHzwwQ/+Og4B+LsEt0DD9Qut4DUFmRxV6lmMZqIGuuRgXJCltxfg7HAcivqjC0BVp8UM6X8beJULLBioKidpAKmDWiH5E5OwA24YMroHUOl2C/XmbysKlmvhgZiSsnGMaMe8HGXrwSZ9ojz/B+kkO05zvZl/Qp0YMwvExdOjaftz1r+fLvO+F/HXjpKnS7t3C62dWY1ALera7xF0+LIgssOiJhOJH1WRtXBZjXi66xQ25qk1GN6pn+Zr06gmCNzJ7MVeog8tvC3R4iTQUW5TiN0jJCIMMH2iSzsbM8KplqaB1LBO7K9rv043QQu2UItzQFo04PcJvaMQBkOmYeeK5GXgsIqtKiyOwEmejnz5TY1fRxXpV+/EEasiUWci0C2N/jxE0wqzM+/p7fbxThNBLIH2RyTIMExccDDxv2G2mHdzutK/QPQGkS2te27HST/WlaebpBMHLIXUK1BJAawBax23aYG0ZX0tVe8Pu0TIvCUUspeke5f63IDwIFI5fXgJgwFnfr/TGcFabADGuhG7G2r6ojqOExc0kBn4096alxGgB9uuxf4GWedpksXPoShp3gttdCK3OMPqHFdRIgEvWhhmmOvt/g1Tc4PYaUnQU7w3QRhtZuOFtrKoio3I1StNwC8WfQ6Q8lFpfIiJGONPN8SJqd8OMM8DWENBU+n8fpAvMri+PWdFplnsnDenWiywpW4Jr8wDOLNS3OeehccVjPmgp2CFNH3l+Y7KOGgOdawXtF8vuMax2KiDsMS4U1QOYTMv6r8iW3DFwfg3gZyNFqs0rP3hzngl5Lcy3vn4pZc1IaIRKw39IOzllfUywGA/5QFX2dcxPhCTwqxX+icQHm9cIdvqe6oNy2QDmAgX5W7gagulonRpaApQIeSTmvPl2i36dWqnQDeTceeeqmdPWqqUh5Py+HgJJzYWc98QNhF+Ll+g+rfs4aKVQLVxjheTDxrsH0JTv35SPv0+5nN+6LmmAkXr79g4QVWr3+zxV61LrObveSeVWD+7OVk1kkYZr8bI6yPcQt0haSxYYVRlqYMpzyw8n8L9RyawKTa+lkYjZZjCWtzRD4TanAY21hpVAOIwOhBXHlsig9HJ/KcT6s0ezAvgzEAqCHD4qQI4cK9BN8gwzWk5eFOmUx+3mTd3j8xYLX8xXe22pxQhxOBkrhtdpTgnaw7MR1t8spphsFvjqQr+K/AmKJy1EFPFXfJWtvNnJhNOB2K5KVLF6MFEwK6Xb2XpjQMAHdwjDhKFN5dZfOG6OCCv5X/NlGlEyRi0rH6lyqpqy11r4V2g4pdpFOcqKbReDgyJifCPmZziMK5AIXQMl2/P8EiCRb1QKLx83DuIx2tj+N58u/ZIzBiTkzCnHfANPwe1lOkQJRWq9gDUk34Ba7FA8buT8YZZ04ZNgq9lXlBYrL1zwTFm8gWC1SbpKS09SaBa96qQ6DID3XyWPdTBv84WbPKz4V/ky3hS5rhEa38s83EuEGZ8Bs9DLfJkQOV12XEyQYLOUbEyu5m4+H/8VO98piII1PSqmdGZvAx56x0DH8yTfTFuI421grtEqAmvR30WCsOfUw0HPUDFdmb18JoktQmeLBFEge1RIn1mRMQafaIksW2CM1CdiyY7Y/an/NX93EY9fZC4Zgc/CP2UVg+ypStInvgbdPd+h7EW8+JTCgRuNxf+o9ktJ19Z4mUmgJV3JFfhClo+2DoOoftifQFab9yFecSYocX+Lp2tNiCJlJmpmQE/p2dLTo3/ncwU5l3/cA/gzRVp4565tUiYo3owEK/U3a0Ht6/Bbju786eJ730KohblBaNaBfaaX1OTwEa0X5hvV/lDoGXi4IpLW+rsyA8/UaaOtAdnDFIqqYBxlQN3SRLXEUEzjzQtJYwDedEX8nSdnb6ddgFdXhMuJHutwl9fRTQEI623BbCC7PqT/Z9nqYZyFd2lO7Sw7kvMGT37DLwKGHQX9mh++Ye5qMhBCDGGPyti5KUNAXXsuxLRjT0B4V6gNYldeY8c2wypf3gaoOWwwNpEm2p8iua1/T4WZUVLlyPLJKzlFMBRp067ydeY4ltR3IqP0B8hJSBZP/0Bxoe680/XkoWpomt6KVxHB0gmTpuCRl9kBWLzle/UzA7CSMXByAnoslmaOQqZAy2Mpsqpmg9INGhqIUvLZUnfG/ENbuS7szyBw8kbi8J/6jKN4ZC+oHed27EhWRqMO4NxCKWeTjwTTjon9jVExXJbDkhVhi66Z6TcD97jTmiF66S0yF5VOZPX61Um0XZSagzg2ddcs+pfd/RqACb0DK17KJg+kf9AkCoZGLiXGxn0g+9qqxR4tNes5ZKPRA76l9btkXjveHKKAQPvmWaDY55R3kXgxHxeWJCUKwytVvLWTVEUAYtMRYtPZ9S7EKQmI/Yvx0pdWeohGLSX6ai+HR3XyMXGqaJK4YSq9hkSE9lGzTTWiQ0wKbAY1MRLQ6UpAb6wDFf5hEljxGMM2sXPjrHaXixkZLctKs8MSsDjcFH344F1gvp7i2ya+WOjdwGVDwHJNHiFobPzrmvi8ukAz4V4+u0XE7EVBWl8nq4ChG8O0NsauVPwzmICpK3nUvjtpfEgnJpROw1gVZqPGOKXgIW64BzfswsJc6f6EQcsqX6O5fP/u1nGM0OHD6Zg7Bz+RHjN7L2bG+DKzX4CqBnDKs7RODLmdldexCQGleoj9o/Kdcx9ghnyi7/t4KmrHFKIjWdSWdZKaSnhZbCDJeGlqhs++/RuxLHRLKx+NCBPW6jwprsc0f9HQsQJJOnhRbt+zDcC2SdE6C+HRUdW3GSikfuYyh44le7CbO47BG9PKBHYoL25e96Vpe3ljJPcc89vyUqAYsfDubW1BUUEE/algOv7+PQOG8QwH/ttHv2eaNkNZ1oTIUPznSteLrQd6fTJX3ULqC+fpTc2PyvcQq29Vu3hVVXfBneqFvxCmi3rwn8BGFZnFiAIAon3qm5/WNBsItzeYQ7dggCFBk5sI2D8youGWxEwrr4+UEP/P+ee/W/k/T07Oj0AHhlJY5uQaEKgNnOBmfXpNTtM4yhZ1yuVVh3bubf7o2PbqWFebuvtk7r12WuL83kqWN+VOmCyldgtgPUA8wt2KleGQcFjtaQNXjCSSjOoe5A4GqFCm43wCtP3a/9aX7bk1pyXoVIYEf7kJhmtCL8ZthV3MXw5zMSQCeRgLTwJh3/el/H8pW13v3gVX3kgILp92uJi92iMkb3LIvtsKM3WDMBhRZ3o8MW10g1DxIgDKxwl21Sw8lJZQ3T5AFzp8X0dfq2UqFbCL4Wdmskh1t8RTZ8HJcjHYI8oDlLcfl+u4SS9OVLG9+nJgHCT2+ei1VYsBqQOsOnFRLd0Agmf4X6eorn5x7X2DM3bT9/dI3YEp2u0Ys4r5XWrZDHZ4eRDdGXn60PdmEPeu68FRDkW7Qh+roObW1ONtakxyuW+O9+NGwb+Q1iYR+by44LzBtPL6kELiVSDhWTWLYn/DH5AuhS930E1y2sILHtYmikeomhZb0MGfC2MuwdtSE7DDPRPZtZ5YJVw0cqgPxT2O5agPBxpzkc7eamnIsSRjWCeE5Vq+h1LYgE9NtY6d5ZRjLr+mVxp1Ar3v8+aRqGzjYhfEKgJaWmGI/PDuWYr2wD8P5IeNUn/Bl2YZclMesZpS9YftEp729sSOBH34THyeXavr1zu4cXQlfAln1B5aLgU/I/I7ig0Bwo0h7XxnFa2SxQkjy3WzmBRwXXqyfZh9WKd4rLUc2sKvsaeY1Jg6stWX4mX5MgYaF3DjolxK9v7cAml/SDxxCZYyO6SHMxif/EnL5pJPWdrXeS/e5wXbYkDi7E068/dDxdNb2p7rpQRMRTNPSQDlNL5UzaKD9Z51f2l0ZFSCAayxUl/6Mvh407TSaw3RsdnxkCAykhFfn4pq/4azyut0zf03RlfuGJI+SYWg6jvNSdyyrUllFsPxqB1tRDBKDAmvaLWKKB/1b5AgAgLa0fZcPtPbl5G9T02pGozcU7I0nSTBvIYxDvy1x8Soit9dTgFoZZL62WWlNrg8Jg6RnnChRUk/E5PLq2bkTxupEtKuNnGAKfEim7bUAjkwJKe13c+vHnLfWUoalgCgogLABVH3KpxjyIFqIBp6jiT/8hMB9yfQTIZzrUnOxEqP7Wu1OT+i2/wTVDoIsuLH2I60FC1kC+tb13/I55EEWWdxzdY2qIgVwEOVkjIA0nJkIkLZp5Sue7d/aA/qC5ObbavhuGKGZYILBArsRzuk6z6hKl0+39H6YcdnnCcm/snPeUNtxStK37gIQH4tKx2kriKAwDgQnwq/IwHwUSc3hQ9dRccN+ilGtoaCY6ohIUykwOEG4XKDD6NzhtWl9i/6pA49Xrq4fC2Udn1ecxrVReq3PM7TK2RYCNDqLWCtUV4vJVCyY8Avf8sRCVKAn3uXdRzKJCZIdIQzBmBGMDdB9wRuaLbhpOCZgxtWqQ8z0mT+DP2B6a9aR+P/PTcDxHEXwlqqmZc6boVWLHTxWvyEomw35IfLnXou/ZdxEyV2Cqr8MEXfbjGTAA4KEeQtciELhprD8oOWYT3iFw+nJHQVNz31kStQvp2WO/gUko5QU+hwGXyRJ/UsYVE+SA1uayZ6QlxWWNXUw1SyWlvenrH2PLChNoHhOkBzX9mbVGUlpbfUS/rjHLpZ5OjD/VdsGMUGzSoitBLLJqpI4/dDQLvYUxMiMxNSSPnXmeP9QMPjv86ASmE0/cRMOSh5KoTFx8IhLZP/7mS56bsQ9F/5uveCjxcMpX+OpdY+MuQifnTXK7I4BryAm4Bjw0Kg2XHh2rghMRPOYsIECVbcj6pXcmwIQSYbF7QTzT3lFyoA2C8Nak/bc1QP1B/oZ+2/Iad/8Exw9B09ay/x0MSI1R4Y7Md9NWP9+MVz9Jkg8FUnTQ2rBKjOZQX70cOzXZ74ggrx+BzHra+9M5+VAWBoE7oDN1/c5cJKaYCfIPaolhyS3xIwuRfjGL6OaZHdLlRvcYBRlI1K/G2E2GpUTYY/wgVoehfCqY8pZ4UDTsFhU1GOC+N+uxiS9JoQI1+FyDMsgb7rJZO/CVMv6o69iKnPaxPaCt5+c2Dad33dQCAopMdsN2cItE2/tRAw1yNg7nVB6jMI/87cW/L6RF7aQdYj3aj0mNmOp11Hpg7uXyg7WogCJuY0CdhHOUZzsuBVZ2SuutvKRagv55Zm6sNWRhIDtOgnZy8XbEu5UtyvyNRc7qTQHBEdYiNwC54IX8Yj3WycAn5oNk1So6Uesfnti9OP/FrqhBLNm/9HVzYc11WhwG89avztTdyeGv5W0BZCYzSrQOHkca3EPdaTF7mnHr5m1KJiRytPACXdpcGrmuiGXIiJQMK7LWbQwkuJ4bVP1KsuoB6N25vHQhRANFTqYmtg7pCHnwx0S5qVVBjzynrSIV/IH33J7+z+VnW0cMnfHmah6chzLSuRk3gJNIyWdVWLHUbDn5ltgKX1eehfNRF8cEhhXOMj6K3lf4zzBEcFxb17JBi2r1Q7nhOPCGytjWedKFth/j3hm4t59ptjIV2A3Jq8VkaBqYGxnr4PTB+drLFYImAk7WbiqY3A0cMiNPAI9UKz+rmLtLea9oelJ0Aw49AlmN++MdC94NBmphrDdQKz4PF+ejnu+HqFqDrETUQiyB/Q4hJmu4BG8CYV1VKP5EXwLZGzQgMRee5PgGOAvnoIzP7dRGjBTkJmfMT/TghPylI7liIUnb3+9ZtOvBJK7Ji/DtCGR4LqIh8p9zE/5J6qDWiq/WZb766xKTtuh+hXjFoHYc4ksC9cNADD98lVrKM3GyrzTgaSRjLSD9MsXNv85LQNGM44eWU2zBh7w4QDOSVCr6vR7SfcyK3sAFZTjmUiBRvngQ7fessaBGmfhOt6X2qOSfHlDCVg/kBokjQoJGbwx8c36TRMd66/QEAze85yotlXIyy7I1PKUIzc69yO2mQ7Ug14zdug5E8sGAcuaNvPiIPBXHpO5MlSs61k3UmKJYxQI5qJb39fT/IBnyzKJTRkS4DnNfj7U95XtI6ePkO6+1TKPozrLNs8exJ44Lmu8buiUJJ6p1W9NqaHB9zmsY2bTUff3K4veCGXQMwMZhKIA9DVUHJq4k2IPjg13iOIlaCcFwAS3Zq/OZTa+wMPQsFiYw6iw+dfsiJXYguKWTzsip+PKfHpBJpJ2kVEW75O4NtARb32IpxRScSxTnfql9aa10F/TBWTmnVtOLvbXVXOnGel6My2Vw/yXv5eUNxxl+63hZY4mfZeqDFFwNn0e6awS3zuapdG3edbPJJD25ieZ2yDswG8aGudMYdt72I4Al1iSlT8LhfzvhERJXyTQA4Cj10U+JAzlw1fKAvOPGta5QBQiU6tBAnfKkFTsP5E3mG0jJ1BzJn1GtrKkwQ2SXn6IGAjKrsNH1DfIxXo8YtlT65gVC7QyeQjpb8uVCU2KUIrmW759BNhQpp/SOFhAzFz7eoL9Ns7URW1Y4ikDOOmniMDaIYptSR8GFmcUsLiaH8dEq0BozKKnD0loFm5YMvH8OkXmeabOvEQ2eN0KrIDBOq6W5xlsKzOVwwk/S3v0sNt/oiHzbGrD40FsDgTECpKuk0p2WPLjCCQvvtg9cMYoi1m9MnoHJdxP7dLmtZ9SFLntPnVeQ0cVvbzQ5h8zvH87rz2H/zkTrZ80zvrXJo+6Apa5cKirsAxzmpW0YSoPjCR7UKC/UtE3inhqr/SiiNqE+a5TpwDApYGMidUXwyMcqOTEvecZWR2J3lvHb4kNpI0qlJYDkraybyf04TP+kX6Vq593KIzJvVx0T6d8P/80p5iBja/1Yeb1Y6HGb2B2CcS3kaWNXEEQuyAa7GaQUhKSGDSIYl/P7T+sco6qOk612CIT/HJsNfB3tAyOdPkXy5ckI4Gr9b+D/DOZbRQKkw2HwVXSMZLi1VFvgmRjakmIvpCJzhWvF04HbI4jICFwRKSH2Yv6rMpQD057o4v5UzWnm8HLaFCN7fvm0m72BBoVbwfn/ZGtUvGg+1ZNkpfmk85nS22+2YkJNYyQFoSIDKpi50/4JyulgFWZ29MaXnzVvAD0eLGuYiM20e6ZQZUEZ95n3aadVoXgyd8dGu/b4zJCYSk0CcSOhJQJZyeOApSmoFeskD0deSqNBOuwiwDYNVr2TvgqqHNWG4FPeOOVpRw+cJCR/EgssP6C1uGu8Y590aPhjGND19aACfbr7dEvoM0bo/ImRTQZy3ayplHLz/sp/c3F3L6MFXg//TqIoQ7/jej+VUpOZgnwG/YoentTvca8xQt5QyRNgme4A7uYVRiEXElSHzFLNxvjxReuGm91HF9nd9P4d1K/dhG8l9Jj79rZJggjKlOaknftb39rCLQvfqWI/+YW7HNPKJ7VrplMmgtEAL5+rpZmnJmYgpBBSb9qJk9CuNvVKte9UVSbLKvtYThC0Vull3Cd9+zj2K0tuvS6YqseMtPRgxZsRKSVpDsxmF9sSuONVP2NXmFHQekNiS5b41Q3RLF+GlPLiDg3t2KD0Cu3u5E3PLypzFit7wnLTvMGcFOtK1LElXcns5lCkoKKRbqQKcDlUhA+FvasdU8mR5SgeVCAAwa8lcnFQU68v8Sblsd00I0j515N9DU5+zT3mTkUQCYtwfxkHeJ38pnlSM3r+kIiU0d9z9VWHWqrAAVyHNhVY5dAYR4qeo6Gdv7ksMyiNHuiHIHRdelqbQWoqsGKc0bzsbHaaQqTIJg1AOaMqtWsEfw2Fs+u6aRIVb6rd/KMhDzWSdfQL9GDfWSw+GYznUS+IycABZzA42uuD5eGAJeuVJaQcZxAj+4eZ7X1zYqvTJhFdFWHYzBfSXXXA2wMXplcUN2UTWgClAt9GupviZAd38LO1oc+NVVClgUY5V+ltvKV2wUVN4tj8gKnR3R1F4YHPVfil7sTzd6bbJlGt42vBZ658cY5sRwcUAJM8uneuFFVT7KSeCA247/Mtmi+O5lckVGJHy+rIM0IdStlGFOX1yk0wJ9zr2lZl3U5Lg17iAPFOkyzde/NWGMyfHcqPE+mJX4ABx/FjvdjtSpZFuIKxGeSU3aUtG2hIOCCvxbzr9s6jBGqaDVTaaobRRCe+p6celXP/Hb3QPlhILnPWtdD4+STJ9Q1ruu39SqFhvAWXBM52TU6bo8eM2cIessvUaOXagb97XV5OK+p6fsHJOOwcTagDhK/rWlYjoqeAUVLI2VHWkarJA9jvt6FYyqOwL9laF0/20YYqQDPn8Q+erYTdGxY6ZcH8QeGOdMhMHucKO53TDxdV5CdHd2rdtUQvczWdVr2/WpDhSWe8Lti93kVsXKtQTpgFwuYXIA+wdSFm3OHkkse7c8FrVp0UZK0CjLj9pEu34Du1+DZ1Wzd/SNWEWAOgSCDNs02k/Ha5mLQKwBWamnSlhBo3rMef2k4xbLUqVdoG/9Xi6i/D9NeCSOcWA9mn68HfH5N0Unwp1RdD61iP4HUD+6RSFM1HiDbmwlfwUN9nM16M7HgrcZN8vUIoLqI2o04mrvdu9nRsFIxadOBeJwb5VKjVgQiwDUBdkiTP+2nYKEcoE7bJwh8c5ILVJMTFgrzTepoyh69fwlHDE7IK9Qu16naeM1AIK0hmsfoPdJ3klfC3WQeYYhmxdNKmgjtOVCsAUA5GBk2F8cLxIW8xPFFqMh9FRJbqvpaH1l/2ek+gl+HV3gRhjYPfaFuUb6B3S9Y8rPpZzoOYmuID2NpOA+t99W46K+3BzExnnlnWar81WprpVvR3UY13Sft2CIsLblkxOtksn7ZsFO7NuJqdgqYCscsdtBCYRkqbHHDtWu1h7VUih1RS7uRpTkYndhU6EgonpsSlE20OBLMRhkdJbwsqd2xpb81/wxRx56UfkaDbGJbNgOQFm/pmLub0r/m0SA2R9nTET5GiBqvkbpj9D//ftiGiWHMfYtac6gTHIgJIY3GCIF+KTH+cdV1YRUoWz90Ifp1VTO/IdBFRV4vWZqvQQ1UfhREwvy+wL7wgRi+TvTFapG2OHngUqZrgJPQKurOzb2R7cdVOlGCtbROTA23lY5uAE7dW9xcm5tAj1lAXaJ8vxvVjlHK9+LmBBpZa4EJ9kn/WKp/SHfDzSAIBAy0n+Pu8BxERGbRT4EmAAhavxk+EprlAGTQQwg7uEw1icep/fO9pzmZfNIDHsUXZF3vgdnOdKmwuxM2gjSKYcODpzDIWzUbR43ltkNaYONjmvpnSd0oM9bOTHt5j1G5Z9ZV1cqDmOW0ShDlQLbxP6P45G+JbcH4GplYKvz4iowtwo2i8E0oAWKKJRdm3M0Yu2WAPSJq1mf6JrRv0cZpNimG2YBSFJFcRdxOhAAdvWuAG+C3ITuW3bd+toYBQXSqjhjpQYcXHJyqmKw869WBX4EbEji2utQaH0Vm9tWsuMS272HCIEkkMS4bXQYE7AKk39x35gz4snIWQNgWRfJDrx8hewYzvfm4Uq5zD4AorUZYqyfHphbxrWPGUvSwP+4BNe3ulXLi2r0DfioZkbhFV282cyHgJSR+6FbOdeQ4S4c19h+PKByq1uXDRSXC7FGpLj5eQFJg7/0hRJXAhxXZ9+CHnQjp7jqGbwDJm0P/BcF0U67e0DJrFxFciREgoPhbfWitArVGC7xf/P0nNHxnMQrn5ZtmVO/5wH79t6ZCTaiTvLdMMyHML8ymubVWkG9ncX+1ywARre/Tfo+5IUvA9xb6lwG3F3kKHv/BkBBQjhH9sgNLxNck/k8PiXy5CJ/66AMskUEaMRJMAFfz+qdwlaBeuutGRjBuXpdR4pFPrKHmmYfQhaOLpiqVw/zhAEMIyhlXKPj1vPqI46Vwipou8MBnb8gzVxSwc9YSHMPBj21VlMLZkwSbkAuwdIIkB+eNfvTsL6Kow3DRrl3VEdamoTFBD3CZigeaXlrYtCazdjXSQ+UxBECLqE85dUz3Qh7uhC0sbWhLk96sE4pnrFn3DPoYhC/2aqX90sFZH21drBs75VrZGrGRw96FimVnkw8O06hYfqOInQPbbKQdBXD/i0cF1SxXtjMzUJWtE1VBoAUiTtX8wCzEMzzoTf4vODBgWNX1bVrcoXi0d4zE3mTlO+4gRm9Bea1ACC/cyGIyKRivrTd/pZFET47iGVWMHgJnENDxCzoKuWFbXFCsrDFKKjr3PS4S3UgJ/3tO68mF51vnkeSxf1uABwwD+D2Nh5pf0YscnFkUklE7SpbyJzRSj6NOqHwb4vJkHsFtXjDBUukvpv43zwB9LLwBR1mnvikG3a+r5/lzMDOtJBI3eeD8OoSJw/QpfDVJdk3efVQpwmD6HHI2GUtkPj6Ib4unb88jnB9wZ+lN1YZjvcOPZWUehjSvyjoq/+nZTodlPnkwLpm7Rgl/08w56RcMdn7ch047DhpLx1QIVaVCMClz9k/mqfDibmhkfz9laaWCNbxApnRgKFtxI7Vp1XzyYnIXXDCdfidsWJRqQLw2hjcB566RHVpr8vx8AdlWCBTwdjzRKqTwC5RKJJLyEf+AHhLP0uyCPTwLrpqFsCZUyN16QF3Ue3UuRUcAlEBIWaBpDPlkHNOQyPh8LGedzA5XewYFiMy7FF7MBHlqk0Y7WW2jTzRh2OuASh3Jh4rrxgyYFIEkVnQJxZud11qjaN07+EjX2uMh1L6f/bPOSBvbuatkeWluk6N4JFytj9z2PCkU/OO8A4keCwssMj4Io5XaAJxgdWJoZbC7Tj/bziKp/blAjuS4vDndzW1PDdGZ2H4gQvhXChQAFnOctiQGCO5U7W1mlP1t+aP+LXHvykvETATDoOL0hnj4IWTBDJm7/XNX/KGxPmuf0pVnXZ08CoklGMSjaxk9elKRloLmjebt6NT7flbmMprU9kpzJIFofT2I8Jp61bEtXx8gSY7XRMkr0JCKraWGhE62bztRbcTXUk73UHEiOFuDEZe3NvA0KIeAe3mKsWfJOzdlfAkyH1w+btnHw/U8fRmyHJR5KcLFSxq0vSK8/dCj6+7YEU0GB8SW+afmXmS3AlT260CzxMlc1yxgCxqvDdUdk/zEoHSLhNxW0oqVULK93rRXzJHafBtRfKs2cB1dKkvrinHB+qH3m1182f6QX0KPanpQdPXBLBeLlrHwWuHuoja4zWvpPYrTy7s4r9FV9zZuyHKdqb0Wp3S26oqOXb3IlZoZG1DfLEXmOah6M6hAa/bWt6lF7kd2xMHwH+4qn17QB2YHHiDX4O1PGJU0bAl+DVyXr2+C2hp15lhsWSrQ+GSB2gyNSLqPie37lwbRpfFYZSvBFAkdtXolaeptvAiLM7/LuzKF8mA/KGP+GzlqZ1iDN28lNSmYYFHv/iQWItHwRzfBGJXtaS1im9E0y3n+SiW6OYg80xcs4h0Q8iGr4CbaBABNZly/ig8NrBC49tXFoWZVaEnP3MEu6zZ6QrmSZkBCDGb5fZDpBQlUI2ecBoPxoI4lIak3y0EjnEVACsjnfP1XU8BSpobOqZRZi/LEbIKNGnL2XL9uf7cP2U25oq3qne9ud6MCcqC7SHbsYYBq9CH+jvKmFkbwlEz0Pqbd0gKKiCuibvJnxoD0irPL1Myg8KnqexD+pfucUchtH9jzj/xzXvERbsCMq9yMw8ipKB3cfRxfa5HTmUNapyXuzIJekjOrK856oU/jEgD9Sy/P8SZ8X5Gy/bp/Wl6uI1LslePH3ziYYu4HkOeWPoG/5QsfvVn6xpxCn6A2TycL2owell/EUskdLlgAsNUsRwaqtj6C2x5mptow8hwWUadoK9wB6eykE1vYRd2aCt0hSIuhWdNAVRZwp8aucK7fLwZ+N1j2fucrfQ/6ilFfgckOKRX4vcyBWqsqceWCach4pfPk4GHY6Iav1zvaX5RVxKGfokc7a2tjqNdpQit4GtzgnNx+SOD80Hy+tDdv4kQHw8rlNI/8CooD4Nm+wiuntHg+CydNXDtbViCuAZl1Yc2SveZKTyTf4uSf6qRnDnEN7cjk6hUx2HdvdyMF7UMb+N34CiFiRbEsQJoeeqUDRWc1Hrrd4ktOEWEH6uuqgtXBg/NPldXarew72JMjS/LZX8EdhUECQZDko7hpOe0vtnNyyefV2R7QtfgJOn/5GlxGBMIWgII+JBxcNpkjngy++p7e4BUDMbKqjKg4vpzu2I4rl66vZFqsrkvyhlEC3iICBYoBcVJnM3EqEsglKIU5nTQVvEuUbITEsr34ALWaQG9rmVr7kDsxArFSOu4ZR8ml5HnhtV8SEZD8SCxwrmqGcvmK7DYZZG5+vVLuluRjommJQVaFAZrSFV22+xXconnJuPfPw6Tef8eXdjFlB4Gsm6iAT2fhHiWgh8I34FWs4d/ATeM5s5rlCKqTYwYNA8LWwgqQbrYMSkQrKQ5Sn47Z3/0WhrF3EQ9kN75x2ldQ787wIvokSg7gFPd/Le1lGqPwBWBxlfIf0Ijs9PqdCSnh6vS5G/vP1LSgq51HX3GW4e+GIQdkvHp1WZ6kxGGeqXQFbZE35vQrUVss7TGml/pMc3tcg5wGiOz0ujIGCfoUAmQ9fk+0hvRs/EO7xd3KVcmQa7VNaYFlaQBcBHXyruCyosp5pT8pg1pIhFuey7pS2nA5cR07iW6e3/bd7N8l2BnpMQ0Z7y5z/62LWI+MgQxVhYSGgquvD7yiso2YTy0K2Me5gy/4pIY/fOdI76eOf1fPWtKJGk93y0UDb9fYW1QVpx+CdtdaUQuI1h/EoDjQ3KOBOFaqG1ZLEmQZStMY40f+GCW5eU/PCLo7DFT60GrUiz2UklAYvAekyJ6RaaJC0q5KAXcq8G3UJnDLfCzdX8qpf+rh4rjWqaesmZ0pEskSrkz+t3/4C7+pLGyiaXSMRzfpTamKmlJ4rYvuU9aAIHzwODMZnd7BRMa0q9IVaa5w55twqqkgi6ZEp3HK0CEwgQpUK5ELDuwahzqaPIVw48Iq28fiIkUHjOfSjTu6NnbkJj2jd35O6nLFMAmM86lfjdDQuBqKVLvzoZ1vD5e45ZSfwAwStzKZyIIkmVPsH2hUAq638X9ceLEHSQBwjX8pW9H5k2NEWzZpC2xpqy4L0PmzY2DzacooJwa6nvUWCF7mMud4h668xPwjWoILL/hhoHZ7EPJyVKcN1VmNSp569ZRVuYlwfYDkRnimOgD/d41ewQb3ul8nGWcyiSvdXQPFl+elva4W/7Z3CRAhVGJtuXUr8xRbQOVf5h5R3KWyIbdQiJ0+7G78ciuAZbKzixA9fXIYLnhlweA1b2rTy43CXpnKINYl+PfRVd9zqJPdXNB58RJxJ7cBD5Z0upLkJJ0tQBp4ES4vcAiS0Ea6AwUqAxGnxV97VsFU3cZigs8dmTO6+j+fbLo0MF3tYyiAkk8D4wkkPyQ0vSYGgS2w8gpkCeOLTCSbbSiAI8FCL7SR6J7ZPqKRSoWIzzdk5zAJtw2VRydWHZ9gxpf1DQAQqBegLLTXA0JN62UpIlCF1LUZIvIsCwFDJYs+dYoTBskjnoB9JAPwJ8gecwXfWUUmxl3vodScQ96pT1OPXBLOyGzy+D93FlWHOSudxmLDO7qXmfep1YfsENVlxeVoUEOfYCCq6yYZ8zdTnBBEkk5jqC5wMb0LMM/JPPJZIoLF1Pzl0hy1Z3F57M98p/9F7q2ZGe8Fp9Hr3gmyIDCmUZswdOxqNV8Jsic5BV2Kx4fbFOg4Ajcx9UkFneCBNBrowCXSoBDeM7HK4vj1CicMQG6o/A/AmSJmAeJkDU9Sg5YeRaauplS2cG400N+ut2dLZIOqap6+9iuN9xTCMzeDjN+4QXqMplup6JPYuHP424RIbCNiTl3oyA4SYzC2MQdN2KuhzDjZS6h9R1wKTVIDOtgifAtyvj3iajFrNBWwi4bGZ2j0adndmTtLYEAyjKHit95+l+fmhHs4e9bzh79pJztLIvWAfZHmqHZ8e7TsNHcxgPPe8eeK4XSkg6XD7NBjfdz/+acz8OnGDgzQW+3SOXCVABOWzLEOW2oYDTZTkoh35X9lp0LUPOOnZu/FUIPPEpSnmIBiADjcCHS58v0I/vzir7hBjfi0fxLnhz69xBSo9C/1NQB89XNJCut0IGTnH5lJuloYkYsl8wqKU0iGtei7gkmAJonHOcrrNmfkMizLCmjYeclOF3WS/55vQBWf41yUt9Q0m7gYVRPfD5/zxdzO1/xQybMBFGvtWKeq8v3sAq0rhtomQWdhsBrPWdKQbVTytCskc+jpaIVrQHO0w2EfyICIgV67CpXLMM3zgJuU38/m8O5zj1tpAIUuE7Me9vBAC/KSZb34MdOtc6A9aJJbuD5NjNaT3apXla2bXs8baRznPfSsZ+aPw2aU9A9K6p8izvT8/gbdlnBGdedAR/T/FkJNI5wwF2xTIhr/u4V720NtYBqG/ruBjy3MgvXhgmtREB/Psx+GWzWI/ikPEAmquXUigKi63/lv5YRWr/upTkcsZ/mughZvQ0uY5FgEB5w0j1CUsv3f9pgBUrmMUOTSwAMV0scgBfYZ0i2XVK3cPe2WU+VaIRkG+zssadOp4u1/Kg3OBMPmKvLJFoLHWVqwWY+hdv8UIVJTkYuq6s/YFDgUW6zjiKmFryyw1YN1jp1iLrg61QgpKIIGln3MquiY9C5+/5cU+KCD5v9RgNw7xl46GKfZcsnfl60NM7jsZssgkik/9UxqyPxzRNBfnlYJWU4oZSusWPtUAjKi8N6LsgsNZ6SNowwaqh7ZWS2VlID9Q+Jfmk/0x8KX09JhTTh8EfW8A+uM8wI89YLSWlx4EfUzMP6XCVTUTQ000WOjBKUjN3zBXP28GjMSI1SYfXhSnFcvATQ7fjOoqnXVdAS9hwjU6kb2unLqJdafmSZXMDAdqCROEaONT2DinWA3v0jP6mXBHKMDQrU5wuw5GSlmwUfCIy3TzjKyiRoIASa8mjTewJ63pltDsQlY7uYkBzCJQZN9UqfYIl9pMDw25ySYvKQ53+Bu1PomAnF63VW6w68z3JDhvtWv6MLDj4SbQ1tmEPyqExT1HpF29egNKlsSu2A8d6B0eBbenB6REkbZ0ueYaUGLLCol4vfctWaAXwuKQr2GzuAr92c2PGyLZgy4RwW8rPCzQ7DVy+r4CKuKKUK/+ssRGhmJySylk1eFA5XWLD2zT/rZrS0I1KUe5g5pNIQTHLpk89bPvwoIC8/oeL1Lw+R2AMomZcQ9WiVqsAvm/9pNln7gzl+0h6x1vvoVJSe/7jrZRK7CB+qSAcqb55d6VIp+fLvO3zDzxuZAU8l6DiPCMj71PKVazilPCkcUagBC1JLoRpTO08WgocJQCdLvN+GJ1zWcx00dUzuUpTjrmxCipRLQHEGLZsOL9ZOKL0N488GX4BxrG4lbCMSSiwvtoQvrgBtSdQ0aRCux1y9KKvJXDHxsmJLJJP0KLsc45M/CMGCSlL3Y2wqvNYklIxuQNb5IqLEpifLAB4aimsNmVEnnLT0lVzME8MieB6WUAgzdjLZWZfTdOqyCxA/0Kvg4S1gM9X6wKHO0lQ9odXwcQRFH6K/u5gkifkCEl5FWRGmYMUMRH+FggqdLrFqof221dchOWGoHxQcaFkB9RF0wpRFYhBWujNuI5n8vSvZy/gqGmlwNFjibU1/3cJQRF8XSWIvuDJwnr3zv+zQOAD7PIm51N7P+7AOI4lqp0OsqcSaCw8Y90hi3H32DAXpqnPE87vg9VrtzK0o2IDBjYa4Ow+P4FtFvJxaSn8zq5U5Dd9VXSisZSByW4G03WNKGi0v2dZJSVnQuW/M06pbtVgjJsIPAm1p5REoqwVtZy4Ze6BPMQ3oON2qyyeXeTmJZiK3+8di7IemLmpxtesGAXBI4NUSt5k0/DdyCntZJ7CyKkgpXhtbJ4B9xNte8up+2VL4d9dLqJ7lVHntgpj/Xk6C3aAg543UvykV0oLH0SkAEzwQ9e4OGn4neZDuWy9q+PreaH7dTmo4Mlt+p7WtUXbvrrz6263ZfObCjj74q2hizx/fzlCDSlxVwdFRBuxNHm0rSVC2ycSjfpU5JnluTk/WMbXJbhyWHgxm/wz/BIQ08uyYuKAd+BSMj+G/JZZj8zGC8t4WoIywA3c4HfNemkUcGAwwcrkFY2R/AThH2zu9fphuNYadINnMWfTFKbHTkwJvGuQhbWlaxvRW6+4xtb2H8mQlpicMWTpW5oBVLlAlgTV/RmUYqIfxDICT7GEbERkM3yPTVQLyUI+Zyg5Xg5svUlygT8QzWArv/+s3q00GNUKNn7S15RrFfTj2doXrcJw3VOFGqLl3s9hiDZ0aSr1FBeOtVOi5qM/u91KP81BsaXgTsJJSCeLghqTn6ONYSou17pPMYG9kGlzoVygKsuOlaUGFdov9IJ/4wSljHVfkW5v6N1hhHigOInc75NqO67uPedNXjlXHNpP10wuoO3uAvyYWEp9pN4fUR54OG2oXQhoVnxf4etNtJNZMQPMAo8I/YLz+NOiELiKD9YUZosKY1Iw8AxtFCXU4OdjvZ8K0RtDLFAwCZeKh4R5vAX5IkL6i1L2nCMymOXbmZWLWmeZaZUfwUvh0eQl26cvjU0JwT3I8SCb3U6u009OBFIj5e+XEfRLP0nLLlQZIEHfSSlJPPalH/aV7nALDzd/BBRjBNGU9nmFTCdazljo7I1fL3to96dQNwPNfmNdbYZu0zr+RlgiZ7ldkfpWApt6uNRyMtqSvR08YwlGXtJnPF/VYZXzvu8nR+9D32a33Ef0FbQQg/ulgRv1OgP131CrrGyzyIaupz7DWNfnVZJAJlmI37BULHcIhsKMEhwhnvxKmN1PO9XVQaKR8MQ7yW5hefgi69g4pxgOHzEpt0NKgRIlsWsu5wMMkaUAzac9I6Viyk9KnUNe4FoDj4sRVcd+5P9WYFbmSmlgsq0gYTYxDPCxqfSKlwELOSmGzOg4jdji1CUM7JAfr6vD6nJZ0Vw6PXwUh0hkzl/C9gCI5bF5wP1Db3fUfk1oUafi+Jhl09g9jLaSkY1skJrVxBQ3D5DAZcIZAT88My8VK0EeYAEnKlmtUyl7J//WBRTE4kRw/Yuczm1EftJqm7Rt49TaIdGqAW0rPIv2/NR6KpYvqGlhDOaqHSyn22FVvOnzSj0seaFGUWkHAR1mgxZ0+X2icyYM6GbkpvhbxPLWR1xwfo1KO1cesL3v56Xph6u1/jCC5+XnnwjWPf8r59zeemR4LVTebjawlGyD/b4ju225jDN5oTBUW7B/SGY5UtJ4hALLti7Het0AaulScC/zxYJEcRL9Yp49EvlGAHm4Y/qFN9OUBvKOHYLg30ue3yJ3zmqz32720mayhudBTP6SKsakWOoK3iwtL5GbyFe64KHFftjlC3h2Q3WboQh9828asuyGJ5zdlSZmLQLq5ZpdHqMv/X581REFPA4V99q89ssZu/x+xxnW+CjNxm4RD5sDI/TdBqOQ4bI/xQEv8DG9wPVJW1048+ARYqn/13CpJ4joeoeHg88eqwwvZwOoylXZ/fKNb/OP6CRv6/ABBj/iA+sosFEcB4SKKHSrpjMkf428Uw4e416ZWA801ELIU7wbHSVXjS0iRj/BOnXE5iFmE3okr7pDA61oz/WmiqK5H6jifYHnicVGb9kD/fbPN5F76m8n7XDYiajXe3/6TzJYlWFOeWPkRauMb8XsEXB2URjGDLF+Qcj0oF1HjHJLb40Yk8pj+yNn4gyM+6yKr/m299lePdYh9wIu18cv4P3k55V1UzuPR4PuHUEUQgv+8+rseRwlxK68apqDKUYlYXvxlNdrfRRWGgyetWCYTAoxB06pEIhvmQ8C7nsIW/9OFS393m542slEK3WP4GS0NEUAb6PY8ws3aZGvthBx+nvKgKG2eL2D49pLB4DIkcO0nm8hMQ6gf2CWUmjBKWTbcsE9g15dkiY2aqdlnXJqBS8ANuX+g2PmF6ryCuBB/2auBZ4kJoR3C8HJ5D7/NpiRjBvdk7p48qvk3oDQfxVN2W5Iktad4zCylmURRDJ0M57HsYsqMpXCCXttPnUfOsJvb0Y1iXkDd2guWjZq5sdBxzixW0+UFwSKoLMqwKQagf/YGFNZKWaG8yCOF4Jk4htMyrvosLadZdmSUdXLLdM1ElKUCWBihPg8ccvuLMrJKqlusFkGPLLr6nUgn8tEvWaQKX8aRaoI35vNQW7mlcmWS6vmcCqg4eAQGplArE1Kr5D8kyH/ViuraonUf4gu1VjzekOCW4UkqKceuRZ8UrBMAlxwdaCu3gGjH/3F25aKqeA/1GzbOy5xPmLSv+rwsDYJY9YjTXEcwxmAWqXAOiY/XQNDNjX1zfC5JJLzVWMJUBu1nMAA6WjrIJk9jKaXX6KtRcVu0+KMJ4Pj9LVNBUrZM5Q9O03scruAJBuO/7xtd0EiUt2ngPzXO025bb13HZktWMtJt6mauNpZ/3ZnL+bLDk60vwqiGAuah3bL8PdFNrtsf4yH0r1ghfpdlvanp92+8b6o68THLnuIo54UvHuWYyn5oiYLCk7NmBnPVgEnEdftUmkkH1Ypn5g02mbC9+O15n+/taCqEkymxF2Jc1Iygm6rocckhv8F1OGlPoE3L+YTPx1YXZ73cyDotyFxBKVS4Uhf7b++9PhaDqr35qk8Y3/ScqAUfFpmylWDbFEXFRNRy6oeKDFMU+R4tt2Vi+jqnqMcHwTBpOupoFmXHV2PEodSXjSuagDkkiY4vRJ+KIYlwoDixE7CpLqA/QwwLP/JECFM99QJrSdTfn/7wBYdUKhq7k9AxkPiqnQw4UBbKFTFvPRfSz1zVtg9hCnknGJJpyz86voRZs7Z5Ncl2zH4GhTX3uxssnfGEuKycpUUm7+eWHVeFB6c+icJc73HiyocZVzHgXPg97iU3TbC9v3EwoQNwGUq4ZiwDQyCcZdqT9g+3oWliemF2HOcKNlXJjQ155fsg2Mm/UyqFuQTbNYM4KxyMosRPsSc5suwQpyaI6G59fruuds2mG7bJPOH8m5ClFXhdu/hiDL6mYEnY6583tqaq6dXzhp8XeP7v9d2oGgUb/obQHWEblqnZNu1/+5XtFKH5gg04h8YOSZUZ/YdontNVAyTzguQifAsQKhodvWwlgzAqlxJBGYT56c+k7UthMJE5uoV+T10H4Ke5vzUQX+CjtEMKH/M5RRIok0hf6/N89GOJ4FkiaUnXHJnMA68j+8XUvQpOa5o13pkHwQuufbQtsCzelamHG+krFbJ4D5Z5x2ME59dZQ4wR10ZfegmHtGLvuWigQlJ4zRsuOcyhlCpJv9tyB7dU/j1mtavgP2MR/5KVMjoQSatXWHe6r0WoSJ25wRtI2k8H3JZqIHTbO2Z8OTtmBTAEoGABPjhlWwuY6QTvr9bmlSQkFV16+kNrXpFj4a0FTumDrdrJ/3r0nFGwTHiYGKKzY/cNTFt+Gz95C/uXWrd9O1DNm6lvx8v76YDKWF7qrmOXRAJRp+EozIxBDdnCFKlssk0lipcNK0Xf9gvvnlAHqxDACxpvxsjq16fitLK7v5rxQRa5GZ1i+G0UXq+ATKazL/itnKMdpOHSHud5/HhmVnPiULEQxHGBEKEKHZLBHEO1+qvgBvTsf8OnMndZ+HrxNoMEPP1qRQbOOM2rx96VUt4hACR+llkE8ewXwWKPROru+EWhJTWpLEMdhhWU6h3mkzv4nMK5xBqt4C118MhjZpESiXsTjqqdsT5D6POuu43cfYdboNdCviP+scm3b1O4RDwrT0i6i4/yL13aUpDb/xjtFF5XIJ9puGQ5dalVXtN8vBGpRQ0uuvhVNfqKmJV1tzYiboC2gVz/X7Zy0mvLUlzaAkpnnAbbEscf6QHS4j5P5NwxwC3UVaNsNfekcrkbyVDPiB1oKtyG79zlx+02xNNVwZlSF8heQAuqESdTcqFVdydLtr4PJurfu1CfpK56+WBnAoRplmRoWhZ7w+Kua+V4wLqVoe7YFH6IUNt8lpJlHSjLG8S5tzOMejv5QwMWyZCfpsQM5+Lq8sLLCdh9DBfdmmvNMj0/2VEYrdtuGtkSCVcuVT7u4mbmKJ/a+eKdPy+z9OoqGFXpWwEUxkBPu437dHmiiYR+FNEdcxPuUY2our0VESoJwSGbiKNm5HAeWWOC3XTlEyoJlJtX8+2PO47v22KEzX+RPuwqALE/XJMxhERTAOIfMmsArKTHaDWFAPoJVD5kvGMNW0aOZ4nxaLSX+zgItvHT8nBSB0vbOPN78ZZob+zAAz5bOrch4B1tA25GgukSFNymHWhVNziOgBKptwHl0VK965LS83R4h8WYnTOlpF+sB34/D29nse3B6epj5W8VRf4KpiOmf3GQXEf6zwNkhO3WIFpemCk0lejNduC5HcBtREfaAjoDzNFl4sAJNyhzlbF9qmaS7kSSFfJFTgMX73UKzust+KYNuGAsNdlRk3DcFZoDR3WZTM5tA6xQ4t2tdaQ5dbxxxMn1LXcNsnVUh6sBKH98ej2IxIt3HU8rqTF8Bs11rkC+JSZJVdiolB7otD9NzkxcRy5BH5r+c/+DJzccYcZIQ/fql3zeNuECtCXX6zfg06cfuD00/CutzHpZEjUvf9SVEbUgJCUsSnDyotA9T5MIwtxXBAzP0XT/jtuqn78o/tlVfOh60HqEuf85udtbF5cz/Yyl2zErYUReFmkIR3zjhn4grec/ImoaW6xY54GcsQKWD5R4Ynj2rlWvwjq2e5hjYaQB1Zd7Hg5b2LE/pwYhAEl3jQMmg+XHBwUaLLI4GLBIKDzxUXTNTL8zySpv5BrdbF0HllohnvjCTRftsPuwI4EPy/dG8WUByACqf+MCyCme/qLu4WRhWKI52hcgUsxw3+WrSGVOU6SzC6ttmEgzxZNOBBR+ovIF80tIIxS1sM6qxYz55QsDEHM/pHC5Ts0Y9ne9g4sdYufiaShOI0OM1zsQCxrwIXoXCdvn8j2nlPt4SqR3sIzlDs8hIPY0dD2GimqXmULJXhwN8/KPeyOdXA8LKLMpNZhouO6DjO2tJWh+ygiNoIPRGSoK+w09iSYHywZyx8A9HeNI+2Xa8mJpSTvXonRFgtWmMJTZeKYaQZMqCdO05WvzUzEAHTnzMzerVNuoUsvW/pSdkNcEa8txGmp+hZwFNHbqoLxmeldAmNiNTWIHEiqgWRvrFhXQnk1139clEAZ1SMaoXFWavNlb9qNvx/57mBmiIstUlK5KQ8ArpNOZ4Jt2n0FF5xytCzI3JybRA/25SSTG2MHQx1qmZAa71G/A+NwstXAgYC2z6CzDinb/89i6gf9ywC8VxIT24x/l2i27X76Tzr8kyIh8BSilOJgY0tjaT1vAj9KJ9YKliQ9XTVnDyQXwctMjpvklmcPbSpFh3OjIqiZg3mRQhVzP+sjPJY1G6p4MyMsq/Wo83n27or9zQcqcDSzjjqIL0uwX3+v0xoCJakZgEObB/3iw+zUJ+YHr64/W/H5d5VJvAyYRD61D2yYqVptzu+w/KwrM5XZfjbXzbl/VpCPuxMnzP3F23vCpG3hj9RsIfMEfeAAFZRoUmFbEaKQPMpKK0bKaJLnRhJxV/qtTfZSGTTG3AnSAmIs0asPTGnLxCJqGDBYuWoT5FSt74DWgTWXKBfReyVWOF+L9lb6b8fXsoXZ/fLWZNF+jr8frIgwMLqQoJm2vfJ9CPF2cONTXin2xWIIy4aONwWNgqeX6K9QYx6KzoFG832H/USKTPtcuvKY8d9vFNcWiuAwXhgX9eL0KsB/le+fAJsqCcssGyqsX6O8w6m15aksgaEmc9mI7uI3rmxHmLbdhccrp7g78yk+eXD6zj2wOQecTxLP5oSe3S8k3AeSsuVhZu3jmgti+GW3YTyYNxFixmGLmChrT7nOfSxVCHJVudWlP2rJohf0fr99rUFQLksyqGtjcK8RuoP7AFYswP3gaWRyqSA/bXAuZNZD9GKrbQSl/+AfcGAopd5aYtmbzvloxoHB8IztC1e9eb0n4tokedub6sdsY+mJkRPOQh32rftToBw2SfHUL4gX26bnkd/Wx8DSGGDFyKgOVAtwT6OPxtMfYTxQq/sFlGREXrBppLOpvA6mGat1f3sBODcvBL9gXxSLT5vVTLdlPxfZPem+vutVdSfvsterFMUa6kapnqgbEBjF6MZzyhv9Ju2WVCGkFzWVgXiaU2unfIC/oiCnbGZ/b6KGLVMBCyFTdkNaxmGs9vUS8JqTtexjVGSPrd8pglGXiwNXccHBrUIgPzLZoam5tcsAC1KqJ08rsXbRGQ87uULaRT0hUVD5e+QQUm4gKqWHu9yK6A6Pf4D9sIIMDAXQm3VD6RT6cnmz0QiBBJezc67ccIcL8bW/tAHHxzD/c4Uohtb2c2od0hGyVGHP2zLvT7JrzMy5tD6jaUr8P2V1vIpGKcyhOhCrNqt9CuWYGttIJOphrqrruz1wunYL1vKV9LncxJ/fMTw8df4HBJWqQq0dgfPGoDJ82KEcuZgsyR4SmwoadBH1braitFg+fihUdoLnNLx83uQ/eszoMhU3q/85QyZpoKoaU8j7rORb54w0cVRh6syVLZLNriwzXtpBN4MCmnixRhAUQxV1iqoMJ83mi/OwMH+yMWaobjDFBQQo+v6bd6R8TEOhw8KA4yNyOuN0gxdIr+jKF6nDBrJszB9UK1iUcjY6LbXgNyvDXrZnb0g30vt2bXnRzTWNjBzqesRvt9ZYlM/MLEq6ncgXLVf5/jXD9KQDa+ahrSpOWQWSGATGyfusN+0t25D65pUj1/U+Q+P8Y3KRLKL9TW39t9mX+cKZVxjkzQOxJckZw+/BlL/SBrh6h0dz8wVzuFJIqwpkjaSpxvnIA6yKFoAthQFjs98wSXpTwFQP/ZtU3cmDOGHIEa9PhiHHl6euG7I3iZLBV4jiwiGTgYL4y0f0cpVcEXIGWf7BZLu+IK0m/aJ1HaNt2iRXcrYi9vwL9WwUc6p7zTpW9G9DlVQhkKqM0HC96Pw0thNOXZ/1/e60tu/9VwVY/6SlQpnB5gl1nHfB0eTkEbq6LRTRQbPx0rJA28GzxJJAzbfu81awtmqjQ3xxC/fv1UmgM/wu8+1avBMHpYuLWNECg/M8VitMf3o8ML7I4R+vS6GzXRkSEztfDUtJnvQs3AzxdUoQy0oiUDJTB5z4Y89GpXGoamuJo5T2+beREWjHCVvpmzTAd0JW9AlHIXSpopl+Qvgs8usu+OeCOA0jN8u6mvCG5c1NDB48JIzhhKbMpjCELhDaBbkmqSkzk1wRotmGyxunxI2EXKnFkcTWRPn7KsiYJo2bkTNvYMkP93hh42099VmSV+0I06UVH4pz8V5VgDr1bV96dFKBrk6uv7ImXoZGx9Ip6FLW2k45PYCYEGr7nltYVZeQY4xwWHIyup+y+uZQaFXj5DOVEB/xUG0+blDpuht0wkfsQJmp62tilI1DXjWv5kBBfNizCnWzekwrAYBS1uWxMTdhCXKlyK9NSNDUjvIONmTTZ1GIVWTz1EpFmFDurlYCQaBpKJ1Thx4irfFWl9zjmvag58mnvffDA0SDZTFEzQ0WF9YW9zfCqAAlTotiagCmnsqWwn5+mMT5osecrl4KnYZEX+bTzapwVYwJdYcp3JmysQzCOcHDAejb5ICLEOTP8xF5j2cDegC/SDXcwmCy/ZoAIF73U47/M3fG8x3iWyckyv6h2JYZbU1gkvHzvSZvIJeIfWusuM04ihzPwgyZ9i7JDeSrY8ivwo9Dl1+w283xaUZJU4RzGgbm7DDfLa5OhVPxp3G0NVk1uzFlDPOyibMawpIFgUCN085jDHuT79Ir1EcD2Ll3mgiQK4JML737kvr4FBFfMMtJyN+eWE56I4Y9m641Vqe2axt7rUXUukxQv5LTLf/bvmJq/U/68hLCSAbQw1+jgcdoteeFnkSfEFGC+d/1g8B+PYLPLYSDZsW9/PxWxsTiyZ4JrT5+oEsa0Sq423CT+HIFgKLh9MROIPAKS4zNC4mbmDhQbcE0xhw71vob2XXbgzDO1ybmIo0m/IOpb8rxZG8yamcDvFH4cR3RsbJSbs6vGf2+2ZnrqPjCj37ikj5y4PWZ3CPL8/Kf4Mdf5aA+EizxZM5pG+PNekATrPZW87tMYq1k/rIR2Tc/CbIcTiI4b1/Xnyk+0gptmgbxrvOjcRibps3jOmNvyl6FCmFfyHMeeHDaBYS4N3wa6bNnMxuoMnTz+Bzc5wo3341VIAMtGh1uTD7SvN7ZAqLa+CPB/utaUGeMscGqjfLsghi1TmMsi+qG2KEQPAHx8i89ZvsUHeKgWLgjq05dPwtgkF5hfd2sapGzuF7ZvpKvCiuq0k4vZSjOKVeL9AIP66SiEDHzYl153Vg/suveLGbS8XkeT+BYM8nM+4Kj9yqoWCbjGGAJbBxCCP40WVVzNyUyvtObF18GcKVcuRXxocLI5T/vfB9WI44BC3iFKptvt3BXJlOQYZidIyOT5KB3BmhY/tW24LEN+JkqVaDwtghql3HgnOEWD3yNX6U1ATYqWIEIbmMNH1xDKcRa15qMqyvRI04fWuLqIyFl30Yaqfp+hmng90baAJp8RvhE5H1mU3Sj7An2kl9/+Mb5fZzjEO3PDpSl4GsV5Rm9iZQe8gAvpdD+ko9TwOjjolpuolrjKU86qULZsmSq937NHrRxcM15A7ueq21bKPJtwMik1f6C6zxOBRcuHmE2J5MnnVDxi5RdXFRk2RLIxRO3/lP1nJsaAqzSNFVi2e9gh3MvgbOFUqWYNwQyqhseUr3sOpff5LiIKivP43KmmkVQxY1KtxBJa+12woB1dTzVT3zhcnRM+mm/Brre3a3lfxwWRso0A5purjPppX9MRYGe5OQgul/1EPkr7ma1cT+myPiWWfm9bkQspXZHjlmfh6f83vIRGavZda8CqW7PYK7o9+huWORmUEQTv3YbXdqAbUzpa5qGNqyXsSfoRN3xqBPvqClXxIamN1X8L4C/TXtOmB+k4UaHyyOmJ58Z73uwmVIyHlQznkYU+bst0Pt1ltPA0YEhPXXTBGYnRB46fZZqZRhm4V+pX0f7WEggcAYy3Gu/7CZKEtVIuXjZ367pQXU9oyLeUNcaIhcF+oRABFqqZuEAijMbaN8xVuJiUI3S2h/Z0BCZc8Zm8Yo3IB1liBj8w5QUVuwpBtack3jHdqiyu/J71Zo6nC1jzBEP34SoaKQbP4zpnZWeLKWEjzSkSLYubZnWAO5Om9XJSjXaBqgNIoygj++QFdGbl7QJ4j/Ba7FLcwzl0ikmAT9DknBxVoF5q/sicK5HszX/OXhZX8CCnLQVC/NBAty9zT5ARyccoEiRZCEOLpIcQrqdaQxL8DVccJY73VjC19gNG0QdcwvHjaNi6EpxmPEILyiKLgwU2Zfa263PDRDKaIBz9u0bXbOJWd8NGoHEGPgJV3mcKq3ik9hV71F/UL/qtFUZFQjSgx3MczX3OKoxfR7VcpUMyQ1LsnQGQ0WD6nD/RId3peka5iS+/GCZVljlnvXoNk482Lp176PjbJP5K/ySv43zqsdsGTmIq0z3PtMiU6DfRCLFrfR7SxpG+YDItmlRk6TuSv5Qj3cLFk/GHxA6XvzS36uEvxYVr1w8EKQXymCCfzovQH/e5+HG4zPLiEi5DaTN893LriM1xrAopo1AFmOyrovHQfqiYvT6er/LlbWRBZpM/DbKEGCE8PN2wPe4PLcfsRElHaoh+WthA9LrCoYVy4zlITQpsPDk/4KhWi4E7lJXI+3wZI6Bam9/G+ThppB/6SqJRwAB8C0KKa/x2JDC5unPTSPqKXrJy7BE2QGTExk0dqum8xoa6xmXuQc5yxaNlHmFAj1dSe8nH8x+Z5psWPtTctbvlc2C5M98O98vFRIPUiCWhaSStpVXvi5cbfeNkLRxQUczAg29QoXkMXR7bR7fTLZJwR6XKkUngEN3chuhrdKmOcjidsXduxW76ZiHlC5m4KCiCVuNMnK/TzgkKR/LIOHnOwuJCVQ/mXG8hwgYK43lpstyj5F0lpLPAvdmlhDHsjrJFblJ4Y0g0noKpF5wHMlJJCb9Bd1BBI0zKFmA6+iGYqG2sjL157HloUTU0VzLI4b3o6Sxo9XeePfB0n8jrESTNHNQ+GoJZI0khpxN+lMaZAuwGDHMmLmX75DeZ5YEaiEecFdtEd/fxX0aSdtw9s/57gaCg+hu4HSiJpuePXJD0te33Lzux9ZkxkHeYy+XkYOC23dyESLEdZk9xQamPyDXEyHA+WUH/ZMS/x8ZaCa7G9hIuRoubXrjbNtK0Sk9sR5wpJdCgMGwUXuK1fQQMKvkQQzce1VS3wtddV26VRaDK8R22x7LDVDJo0k/PQr378EHtGglP8tGpHqnqwXSupKJmFhz3M1fnkGxYQUhST6lKUytfWoZ4WqGffQpcpQl8svHVuSFLHu1LebQ2EgMrZ1DWWrYjZn7PoeGjpINeriHz+Au+W1Ty2uhxkFAI5NCsUfpPCfptSUNmdhh21p3PrKNBL23W0Zou6/47ZjHqv54R3clpaz4Gs9YnKwlLQ1k4O0b17KdrMUiGiRhoavuQM+lQZazdYSoLa2iUbhIYhjaqFSiFQEFVf1JwupzsoqTYWny4BxV/nUF+uW4OAr+C2Vv0tWr6GaDbhuPjioX/kJ8kHI75DuXJFNV6PXTw4apbs7V3wCdigmQ4NMLufgzyJ3Qvz/2eMkG2UI+sr8WwJNrinGV0jsp8H6kFLv0gxmwN3GdQLJUNhs+StTUgVx8T+MUNz2yvSKKgh4WEnLwQGrFNC2ybNNEDtqQ2aWarUDkPa0mkPhkY0diJ/hWhp+HdhWbWXH5ofLRJh4D5490/y0GIMKnZGWeEZSptWrrZsZRjfZQaSx7iM9XvDIvPHg0QpkFuDC3UIa56dKUWObxZR6E8cjhxDt0ZkdUadB9j/+HdqIPM7ry6T3IcHCBjIgl0GtLQ2CYP/bePTNwt7j2wZGDpojtcD4C+kNMUToeU86KVFKlBz1Kx4zgLFzhxG/DsKU3V2bp1M9LClXapnyq44XcZyClZtngbG5hyvbw4JUMOjQal3NkRz9UEqTi3xCHF7RkLPQr4NNfMdKYgFuuWToiNQKsnPIG51nLVt4wTSPtYj+RK6vgvTDiNi6wwlVhcqtbp47BPa55mJ5p6b2BALPM45YwHwZaz79yq1bouXg8ESuEa+SKXM5UAvGW+Jiiv6BCezltnQcgd03PPvZmps5Z7SHwLlUnmpZZmYxUGRmXVrhNiadALVxdpFyKGZtcHBI03Y/2lBwR5DODKmI4u9FzVjExxOagzQ3W4KhcIQuTF26W5lRjCj80aggi1hdUllNtA3HXd4SWyL8ydrb7dkBE6j3v0EFulaOrJ8FfSuRjVVGpx4d7mOI8TVBxWiVdZsnn8ifnElTvor4EAK3pSGFmlBAV6wxE4YDOSKXVLwis4omur2Z6Ac6bH3EuYVp4wrWoG8ORyp9ytAzWD53MbCIPE9qjoeSTGzxamxzNjkapbHsQwK9xRdIjT95oM1NGiTsCtsz8HlAisMKFkh+HOMfza6u2e8tmVaoOwNcD3rgtwP/t/YyTt1kzE38XD+T73jMXb1YnX3PW0eDC5XoS1bBZ0IqkrrBS74d6iURKRVuVN06LjyFWsL76lcSHTae7UJm5XlsEnhnkyBbodlXj3Mi4Q/ESrAtAb2QXphMzdyE1w4geSilGFccK4Z1tei6fV10egvFjCAFtmmrLqny/8frRWLzYJovumK4B/4D2YXE00ZQg8TxIhqIPGBzlZ7RApOTfgjozYBKpPSBaCQqp2r+cr0v3pjEW28pniBRidX2wg51vaRZGLs1fteApnMgkCI10WpCKXXi41mzEOVCG8TAcjMQ0J8Hzwj1oFesbFIZuRd/z2l7vvGNHJ8GeAkkkyR/hXSbMLULLFZuvBkeelGd33Ixr650p+0H2KF+XtvmMK/qnnsCDX8NDjxL8i7oGAeIrx9wKGkceheGCMEGO23tda8HPVrSjiXzliHXcrKHto6qeIPH066b4czepVNpHXMugwzLyhMh9snKIQQxy3FtfsWJgje/LZGRDlFJIOP0ou3BDESWx0mLQaQ65xf4O2D7YrywsHhIvN2HRvyZc9Kiu+Bn59GH4hg9WipC9rWcGOzkKX3mAv5Z0aFc7HCLYQYsTSj4vtIVW0zo5mJJVP7fCqSzw8sIqnN0IW7DrcpdL9XRbms8AIdf6qGnC5nDP7D9RFcxzo0Y3Aaiezd/rpFgn4Jn8QHtuRjFZjluMbBgh6d4Y3m0yTiaf3Ydim6rUi/Gqo+bLMPNW7qdda5lnmhfiUM/f2laEG1SkLAVK3tN7Wcp4L36txibh8V+5sxIA/QdtI4pZxZ5HBiQMmjddvEzSNRw1kKo/tHHrGhYYKbBar00C50upBBK7dRhpM5dHo4HgFUpNBG2PJAFVotHWjuMiC0gEh0sUYvbN5nkUQQ0kgVq6JwXVaH0WxSEPgXKJKXz+Q2uN1HcJnoUQnsPKMNSV5BPL2KuHKrVCw6h2YBJ6d9Zlt2sIWC+8ubliH7pddbaODsWFmO8nWAME0ws6qjXLd1sFXVipZHk+Nkhwu3FGUeAysfLHkyItfXByY4XTzPwB/x5QlrwsJuNDHtgvk0H62DBtupjczDoWgNW6diAnrn306cfibJAtH++dfGGKMyNDJzQXeAmKTHrkzKrKQIYsPjnlSw+LHvsfTGeWdPb8DnmT82EBx8f5zcmykelCqKK4doxsWSVO6q9xQImoBq+Fie1pTy82rYbR7wTmkSIPvJo6N5FlzT7MuGIYFJPOKaxEytEe3O+bABq/SV3TL+okt4njehdpdsBDyh1fRlcRzPlpXNNeT9KE+UsorMr9bb/rWXliyj4x6NjeYl9n2cYfP2ueisvIfBZdIJHjmsy2rfjzsc/1yMWGJFnI1W7wGBthKan9CbNyR5AJG4QVwuka+ltIgbTGXm80fir5sotsyRv1cDAWos4Wc0mtcZKUblUTsTR1PTREeL7G9EERqkoC4D9PGGwdqYl3nQoSgzNt203NPUEJsbuemg/jcfqGorE0RoXObxOnYI0nDpT3FfrW4fpEYpvEM+NJktvZS1IKIZKxeQH3dLFjejYq9L3eR2pNS5Ca2ZqvoQieWtU3kAN3gaVgveNDzqBqv0KvuWIyCCIaJiAT0AHqcxR9jSzEPJUNKGneJhIEscG7TPLBVEa4nZ/naIEhscsASOihWLo1imOTedQvshyhQQXRKwonBu4usj0UeKXJX5wZJD3Tak/IQgNCTk9NLSKRVfIbIPQTD4RH+G3r2Ig6JGkNdWL9cXkd1inEGn/BNTS3xWELuL6PR5e0TzQEiJOA6XxWoeDpQpTMZRJCjri43MDPPOAmx7FU+waLF/kBvbm4TgBKxO06+t8KwxERaNkkJ3Q+BEHh2l/n5nai7Rxx2s+mqvkLwTsiOIN+jmqfy2F9U/fRJmMu+OnVL7j6EL05GKotWV3Xelx2zec//W+A1tFxb4jX4JKjVAING9dLibT67KDxoDnC4bLvdjEzw3wUnOw89Wgzmn5Rxu7Zb49Xm0IeQPikjUO9yX+lRrvwj5X6FfSEZhIX5CxyrfWSn2SkxVfI/LAYRdxgQc5YQR0siwpEpOXgS3XO4hk9H9PG7YXRk9tOp/VPMf328LkPIftwrfsPTD8O7QZ++SGktS0L4LmWqE3MKlHm/2Q0hjyuLMEvcdKDDpv2xqfiZ7t8uyRCI0a4SK9map0/TDYfWJKSxAZsWgL8dUB9jwcXj7TKhsq1q4r/NSdfvWbugARSJbmNo2sY7Q/lsyZ715l9on9h8ip18VoOq2IEiaxwJAW1qUkKCLOcmWA/NTJJl2v5IuCl4HP0I77Wya3Q3Xv3ihmud4rgkMo+KDBiBG5VuBVYPw77auxd5XZRXAonXchirdVwMRQrKwJXKjiGwlMd9eZyrehJgRKYLS78lZ3ZDUzYGm8hRyFpYRHDffKUF5rm+5Z2Eq/dP2+f+thcVNaQG5I68sWBCnxHaY50uaXTM8FZbau5/vjCTI+F8p5b/d33JusoUKLqZrzNZsahI/gTje+dmP+vCDLQ9QklaC3dGwhMnk8s618Wgr8H6Rv8A3+PoY5VmreHhwvc5qh0lxZitFLab56y44GlcKCOTmoHPjVbuFo1//FeQNJmoDGRMcXeux13hiL7iVOkXcK4Nb76E7dbMBlK4L3FJ3rIUoWbLxNbg6q+t1P4ymsEF430q9QEh9w9Nw+CGshx3A2AySTI7Drcqrxb19QXlBCgnbDCI4iWAOLdRkXEifAYiaLyL5qfQS0jP5lcVeOqsNpnNQy6a6EYk5yToUBJnOuMlCN/6DYO2SiRNTwZ3bcYUgQbQEJzZXM002BtlMjPV0XxDhGQrmviP2fkdcrJQWeffX2nr/4IcZGYz+EtRFphQ3609WihoM+8QsCL9NYD5zkUBcmnV71l6qyuptvTFP7HdjP+yMtrtYZxZ93rxv1fnkSGoTlE0tRux0xdf+THUYrCLMZtgsmhAkJ9Ry37yunIQb9fQ0cLecnTeWvfhJwDf6g/65Be4rbHUGvjEbQiqMyMSFPut//LLxJOM7gp0P6BGotfKojt98GzAY5rxwWwrdoOM7facJG12dw38uVhsgHSlufx+9Xy+00Oz0/tFJmHSoBP+QI784GUrX2tB3fCvxWlY/qhHjB/TvNtbZ9kyN+1LsU/EMlO3/1ab35W5YCKVT/7qSctq0Q5rKfEH48bvvP0Bbbs+XsxlfEEFDflDLCDKpZe4t9zNJAkFcYqjxUvtr2TT5gcFPtnQ/SIYAO4ufXViYqN2vO3V5z5hYmwSBl1MRqDA3YpiBt7iAZbGRMMX7OZXasTYo2cLX/VQMWWEmUgonDPdv7WHued0Xj88cI4heLPy8pkPkfkepjtc/YtR3ejUb9ekmXjPWjxqbV3YNaOnIo6qh5eVmYnPvwBHPKunM+uCINKcBavbIYL3sQHoEtmxG9hIIJ1Qa/5nIF2z80JcomhQnmQfSsRk4MkwY6AIRXw/Q1sws7jagGKHR11iRJzHLzPkLWnEVhLtVD+a/dc79CsBS22xSl90USRQoES3fVgShXeU8mJmXTXXuKcyhCorGRvwYL/2Htgk6juxICdQg1k7eFdQc/SSVdInfDmeNbA8zNw1MqyQ5TGSHZ5k08MjC0jmXOKgddYlCFjjorbGmZ2hBBjTavvZpN5ElROxXYkt1B4tW2UPfYgQwiMWMh0jxAqQF8VF3KjN8u560gnklF8ufEQfi+YeZZWiM5GEqjQMXfpv2q1M3m/2PgsmZX0+e7goYfeMa4YXPT3rL5jv2keKZQZSh9rU4V6zOfQCaJH23lqb+De8vM9F8vNN3xWYZSlgpnQWv3e/mhug24dfP9ON/ZZ+lAcmsZqF0dzLBoqioDHMso4t5MXRHHs80l4NoDAVP+Pti3YABZYs7fIBQf0WrREIKkM9jZYjDjygZ/hWC9UE2Q4gM9cucfDf4T4SKO8lwRcxY74v+iq/ht6/v3jFIpPbjWEsMnG2qOdLLeHlLcVeFnkcLOxnD0dUzwvWd7PLx8ICsyuJ+hytRF9wrjk1u+mK0M7afj++C7RVbevEcjBX1r/zvdTIv5xh79uwFdPBYokTfLtpk1ppNX4AqwPt+G7TcabqYbdUwONMYwqTTx4APNNH5zW1SrR5xrCvLs49st2/JUodAPdl1FHH8YAcLYIb63HJBDrYu8mWHV8YsAyDbmoDyxi4MlhGAXBR87wyOg5DVBbQmdd9zRT/1MV06C6lVZiRdz8pk3jItDFp3A19urlm5s0pKufWl3/qtVWVyM7v4wA5vsL4ZANnKhgk/K2GUE+6AyLBnmKK22nDin5rlhQ7eoLgT2kipUM7lzWCkg1MrY8GUJMVzet8NFBr6NzUyKXf/m2/WgeKf7HSWRHm2lqdvxfiXk7ItVxQu1EnDpYqb79f5cL2VCtk0wSZAtQgSemwEZ9QjIZgjucEd5/CNlATPL27TrUjWn6TLZksbkJtVZOYmAWdD0XOl+qZtLJKsPXxiiGtarJmnGf9CK8OPt502+dbsE0OyzZz68nlg+FYhcMcl8nfeMiuTlF4/XYj8VY3WkDW0FoXHa1uWDsG/hejJ15fl9K8kOuSB66k6ji7oM2ahd2sn3GNKgB61eI4iLM9ORVYwzGLTig9Ryb2TmNoxQR47AdeJXAHXhw0mT3rX2yaRFn73bzQcRYKBTl1yEBe4F+cc1ZZN2C0axEO1wkfNPfD+FyrxptvgeZd4s6waLonu21wUCWMumuFP9EsixevVLwZWx23Nstw7usC0kDuMNVSrCqHniFQx2ualjrB4Raq+5VHLzPn2/BCmzjrGXxWJGkqJ68gLFcHp1v/Yr9RkOdF9CuLWX9Um72uJQ9WCcr433DThlcm5YygXxSmrwCxRfXp44AMxeo1DlCSJlg9eZeBE+qJQdH0c8pMhPTebkW8ji0Ni2N4eLu77m/P6+A+yD7ysN+l+B8DdzZrqo2WW/0Lk2B4x908TEpezbwBFghxcMMwTaXutMCYDOL3/5OsCaW1Wk0xF+k6oj1M/bqrvM5Kb846tC7qY2R9qp4mFmD0GSWXw9RJbrYBN8vW/bvwiIxCnKW0TKZorvfoJIQ7H0O2uQQmvy0eIq6Yf9DmR87DdTZKJRscjsxCm90d3s3SUrrRaAzzvWX6FH+Z2A7Wd+YKeW/fVHd/J6SwOQIDoUPG7YyYovST0O5NF/tF0O004+i+e//hV+q4u3xdnTHH4IikxJAbMtjAoFMnJ1t/8/KS+8tfpWz74R0hW23sb3Gp3FnkSk6JGxbuCZCVaSqyDrzEq33EENG4Mrs/UFWVdm5/ajxeRhjnLYNTO+7OYuSF6m3Rbp47GojqCdBVTxNk+bRVf4mCfbnn6Icq7pzV8UN1MFhf8qdSRUxZk7bFsCwnFrdXC+Ssk+jfCg1VhzMC7xMf0G8tdLf/r/N73iV0tWvm1E8U13RQZaRkx1kgmJKNSHQIJfb7ZfqYOBBvTk1FOBVI3BKiciLN1Ex2EcuoNYuikTqoEMLwKR0jMk/e5L3N2d0zUvlmkhOqR2MwvbWxOdHTOWJh/SmrUZyp2kEF4DoTTV52FkPPslogqR2g7LOkwHzjOteT86OND3J23bQF3EnsK6WyrXwmwBBBGy8e8+YHBeNJFvmnetkWDLOGbApcvlsPL4X3uU7TFuRNeh0PBlrCdpCZojCkYLEGPnls8nSkrJwBc36gydx7rs9bwCNO9wQWBUsILKUSFeyOGWlx0A6JBM0Gaca6YBp1WtC4raVNRXhYAlFRFiDAH0S0ZmiWRkcVcaCiapZAm7KwDMevmqKgMAGolQnApirm1sPtAqUIWuYNppK8I6ByIcpjgUVnmc1uVXsDi10Lo+VlPyFGUtNdIvrpyzW1VK5iy/xUX3kHzjurzK0if3O7AoW73i/gvQZLEC7vWa6tDuwN3kaXINNJhsVoQmzbtESOHXGR+pOQ6kYEixXMbLDX/9HK2riSMzgrcYB+0zSIKbPdO+wDEficWNMlrsfYKTkLrSrgQPG7/qdTZUU3SHy4/ZFRx/4HOcKQX2H/Oq2e5P8x/MYcssTe5S1f/mzvBcov9TNAfYs2/273FgXh6d4M0eCcZI8DaIUTrloJp7EQBXzeTv2ef7/Vf9C9N8ja1uHAHOicp+3QpwBVGt10RHcAHu1sQCCAXDDjjBfjVorLrtUE2O/tKDtGVrkYArAE7NguQS3qsH+Us0tDAufafOcK3BgUaFZisAsPvXxcEAMAeml+eRMOvWNb3mPPPwq2stKNydmOmnrhgHVHLUvFa7rfl2yO0RYqUQv1vajmv1fTE9ySiMrxRka//cpcQZQCxO6mtHuvvqVnYGQyFoeOPT9v1RMXA7ANMcL7UPqvDVOPyTvSXlPNXPZgoOEEDtbswDY7DTiFjHHi/C77X8Iuc2ptjT9DpWu+jqfG9KaCmc9b531OBFEHsBtSqMDo5t6Gz52RLAmOHE2v/ovVbD1YRVSx153qd4a3skhvfhhXP4Ra3AroITugsXPJ43QxcnGX6rCjjUUBGFoqjN1benomVvz/2eYbAqbQTD8BkgfK1EoGsHbHCI0Bm2zGHp2JOmz9Y3Vncw2W46HgcuKj5ED/3yd7uGcP4ab/FVC8vtwkz/QsWADCMCQNb4X7mIGP1FfDadAGyL9inz1p2IsTyVncF+/O7h8v7AsKj+8jslBpGk+kVWzHoV/Gl6j6Mt3lGGjw39NQbxxlpW3gALic/KemEH8M/wvadGFxd13VlkXz291s8Z37FMCJS/3czVapoge1XW3soYmPt1PLt/lh1KyQp7Vl3MAwdSSI4ED3ZEBIwa70BeUsx64jumD9i04g2o/Ez+0/a1gQgRR4DfxLY7/ncQqyLYvwK1lFa6SbLiN8ldugPvEgqhB93Baap3pWXcDNQtUQNalico8iEWCE3q/uHFUMrYOTKS1xQIIcEuVxwB92KfS6q7ewAkv2WAD48ZEIiAt9FUlex2sqqDuQUk9JefyxXkWAWdPSLNr0vI5RMZrJOWR4nvEPchr8k/O/iblSzxb2KO5JubkBs9ubAx+1MBkDwQ43w7bj9NBN+N0MO6s059l1ZvwqkO8yFC/b6VSU0se64qAs0FLLMo0Y8k5ocbIs28LP/rkhaQyIzgJx7CLABBlgkeOEEDEOCbw9R3HYo22DXvc4U67Vl0dXpzmLe0r0JEi1rqA4567JEtSEsozxaIvieGp889jV+Uo/PQdOxQ+ENIYGA6RibT/UmxdAG2rp3Xk82ensLdWoSp9DXT18XU84wThKnyr3Y2ROoh3zUBmRUo24cyKixh6Kne1a3oq0XRU+iVaaN8muazAxcPpUM26OX7N+8vZoj1gEnx6IqOhZDQFLvvTsHe4OkqdZCJAdUBkc+mRQHUVcTVKPrlbDSg4dNixkOQEU/jF8c3EO3yoKeNQW8uAMRCV0LXh2BVoV8tIyIb27mCi73hXell+gwRkuMa3RUvbaF7ucO0J77CP0eSv7tCPQ7CnGHDwBMkGICfc3CPHE9u0QIuf2v+ueSOTdJlLsPEzlk8mmsSLrf2iJREDkedQ+Tl/MyOFjrmawFyNQGolFpGylwvgwV1kxeBrAfS609OIwKrbswOsfC5kKsp1ILsglfyqRhdEiGegEHR54DMzk1V93+/rLRgz/MD9dD0oV9WwgCfaB7hasFOEi545IEdw1lnT1bXS7b+hW/1MUiK2LISTk7dgGoIc2JK80xfj2O58haZIKhG903FrTzckb0EhBlwo8odK1KEO5lhNZqimsDxs/ChmXN+H8AIwLarOLkYE/f1T7vin/QxBwOemFQvaaDGhRJG+aZ6u2E5rTF2GFTOMm17TFs4hMBAApr2dFHL8vAH+DYXCPQd6oVdGTSa2OUYMa390Gz5jlajDPaXKV4xijHIhSBRAiEIuB0LcWk3NYUG3gyeZkgDNmuShNIIDfqjZlwHvaB3HqJLTFDmHNg8DOzaf5i2bUZVfVTIrGuX6r9f4tzXxOUFw8a4sM5NKYbZi9JHMLDdGz47UbIfB4Ce4Ks8xeyibfB+nKAdT1pWWgTrpC1Etjiufs8DNw8U65/VpXHeNdOprVA+6UTVgzwj6ZBeHhr8/F5mk2GMiIBd0F0gGoWFBOuIvjeCMPnPLMBVA1FQANYQlJZDO8iyIyhHWBLgxPNsO2Wm6dRbpcGUySYpBDSOVaPx9YP5egYKU6EO8ZIrUkamibcOkMv1NmQ7r5HI2qfN8TNhZnLdCFUxMEicVi2CgcDnKW67b5fkTxn0wpQgcP+uWMY6B7uSnI5XUmOjiyOd53DBHIeEmllM2apcp5JDOTfMjzH5y3o2cDqSetPVud98GeSY7mcVJvgt0be4Hi+FJ0VFDRuR0ylrBS0o+3IynxiQNLLV6ggEwyke95WQe0pQrxM7Y0Zky5j/v6csrP3/2I8szYPxLNKtKSboAcTMGcC88hNM7ZZkSIAjR2/af1vjGpWPW7XUaX8RJivpXxsVPqSYwIfGnGw5CbTpsCVBIivLJr4TzkAanYowV1vgHyEmJHmfnRy67muH4JYEcGgn3uN4CBRy/EweOFU+NtO9BFbyw6uZdzQAbMT3kzfvUXYAdGZSrHuA4tN1u5Jxp23zXwTZ1WvJa3ZYRwqrVpkH2NvCckDlO5pWe96WP9cYoBkAt+CrF73rGE3uk08I8cafSN8ELHMfehfR0v0ZMvaskNIomIJeFxez9J5f1gv0j9p9NU6g0UT6qP/bfR6z+kW9exRrymqGoDd0lsoH38phKPF44NW497DIxbfbTEJYEVwlRdUN07PZIvQRELZVopfBiUYNvb99CrNJVVPERNYfpqsU7NrmHbI8HbawL9DI1o0c69KZQlDPOcYbhp9WuKZTWVLMmxJq4q5nW+pHLdFqIkOWtqU37WUUAdlf0EIylLfWd2XZTWUlUitORnmGigh/CILV9g9nKMZwTwyz0HB++t5/x4Dqf8RL1Hr8KNOGtMSDd+Z/N8SwgV/6Ucp47Pd1i+W6D0WtLWoFHbSS7KqI9xiGJ/C1+ia52hZ+63v+vqWFdCyIe6jmbZgBaoz5roHNjxb6sDvMu1rc+6tCm+dx84krPGlP71KkO/xFnCkkeLwPMYLRXmTJmriXe15AxhlGKsZRTx2fp8w5wyhqjypnouYwgIDEeBPmGbrp+augb4k4kcKKCVD0zw9/AEZVhHf1TD+xyDgXsv+yWxUgujrdi0kkzFf0F1xOjCCM/ZX+JQX6XHeY98DybfZQWLTdp5SNHTYS66f87n4c66dDT48NgZ2OTBp/8NMXhSCV2vhbr2w5ALyVJbCw7eCWd1Krd5t3pLJ6gqn+hGUWRGulYYYHAHWMOF0Vq5Ez3KiiDj3hoh/2GhcMzsXu2KVwZP6dmuHrJoYBJLbVgWZH5ZPf/zjYPLqPf5HYio97CgxxEqC9r58aLJUnqFsLrXzdtFcUqZXNrQr4CAx0jtR5ZSW3n9lu+lEjtV4A/qCxFarhkY5Jd1DLxjOMnxdZ7/D1c8mv+jbwtYvfAX5GE1nU72Vf0G/JMolEz/PNI0UqqKx88HK9eebNDzSQ0l6VcZgbKTCeFaBH3jQ/XG3I3fLJyKWERCbt/saZp9KLz+R5L7mJVuxBEB+3I08DsOIqGezH6eUsSy+0to98wjtLw9wXAd3nut9/CBdHoCawxD2miC3nbK5dlb8TV9RzCWyihKkLoqcFKshRkX0Ch3Q6S8P/jmbM12MGX2+Ul3Wbgk8Hj79BBawbHlpAGjxngyb6RYfZKn373LB3OF9BNOD4HCTxQr+338m+IyO87YJB51Gucg8fJflRbcUVrOT4ryxK2uXdJTp6LtEbhCk+UyoBs4xmRZbzK0qS6A9NEXrChRgO+fG2xf4vobZj7WXH232hBvtoo+TUnwazj28A1CFsUvbcmv5dt+zURpYBfuwtSfEaR9gqt0gnfqA3k06teaLlIM82sf11Qy6aKQrziG4sWgWPTACHSBVoPMT1jDirINTn1MfpJ4/NyxHCJvSFkuNUkr5A5l0mPonGyYR6qnOB+G+y64AxmcT26uvN7Jipa3KpO3rJuER8c4tjDa734Mm+qFhPhlqmMmPon7l5guamsFkq+esMFAR+3IzeF/XZCC9gHhSc0g0pqF8zPV5tK9xqh6C2pcSO8Gxxj+v37KnXTv+dkzKjg0SybsVS7aBAv/ZMJjgUSNtoqxk4ZInMpZp7DLPToWkvS8IZxgMI71AUITVDHfY6IslcN6Chv1YHdnO0e630qT5Z2EtuGFf21WysDWXBtZSpVW0l9X6IRKQ6no+LLMtphJzvvhuQGozp5a5YEDTaP2w6EqAaou478TxCgJL48uCzKLIyyE/vbr75oDu6LFw/3AIvLEjk9c5Ykas8a81v0K4kRSiDUlX5szSp9BbmbwRvYBJZOjG/P68JGhum0F3pH5dkWYnNK0M8ulAM/1cAcykLbvllLITsbjIjf0JqBREzJVb2DTWu/w0jAETYOXveouaeN6T3ujrj9yWiqEdabIRbOSqtxVf7EAMBXtf35y1bnFWgsbY76Dz3E5llxeBLHMpbTZeeBaLNLGCd1IkT+cq1efVZeNFIJ3jtCsFebA24LZcky3HGLrP6j/YHAw/VxDnRlIrUzAD9vUOO3eRvdeYPGkik1Jc2obZ7/wHi8fATgqvsvQZltUHiMgbN993OO71/UhYk/6IDmkd1RbbVC4xstlHwPRD9ayy2X6ozmJ0/8xjg0uTqXCDUWkTQP+X3vt59EvOpI55BDp2q74HJyuo9dpE84coDPh9UjHiAcz981eE3WkqCX8EKQr2m9YcHb69VChf0T+Q9B4ppvNhpV10nrdga3VGZa11h7AXHv7cpT4mQkMjPgZE7OQQuc3X5uaShhyYBNznrkILh2ZChCUKMmho7IbWmVaiS4sO+Mxxlh19x8iJ1T+X88GZVWLbng0O4wKyVDoDF7dSncAK4mR73Ly/9FLWem0KqyARm+NbPLQnTepsslze2vixWmbLB+v+FfH7ZQkqT7tnMVV0olt/wQ58OjlAKJSjW8RV/KCW68UyJdTAxbChmCc0U9xq0Hx7NXLtk6re544Qbsz45ck3nybOF4FMAlA66L7Oog11ykxeGTqgKWsIaoGkHuh+Ze+KzU9ILS8SLzzr5LgQSPWtEwBqqvElWJY7ADWLaV2JRaJODSndixyGBzv9QiWgOZZaSb7V1vKkJd/h0vEUllNai5cIDkG+fLmqk5+GmZD4nlCKoUI+ynrCBljRK7kCaclUA4mUuAcaaN3JXjPM5Vsat7pcwnwGbPO7yay1WZm/qWMNcWtERNC4g8bC3dEpTCNavmOvqNL2symcwWBEecNiZejaYBF9yNSxFht6MzC5/LOhmf1Kv0M562O+xC5WEdL2yE5bjoEdRNYuIDdDlz2GzB5ZGELf5nFpkAurhh273arATn6Y2f2Jal9Kkn/XjWOittkmD2UZg7mAb6QYEiatZFieWaDW/ldVtUqud/R8V/BBAH2Ai9BT0tXiosuDQ2u/kCPqwInfZg+ugz6qocX037ucV5cZHixJdtWO0xBHcj2rxPqum7U1b/kFnds8vjlZTdjwKyEuPv94pHhjGVR46hhflS96SYKGdgYoIszjIkP2bCgysg3etqFXmUDzr4kd5ONo8gQg79P9vzFpXFQqN4t5IOZsg5bZ7bcbUV1/dsSGxYmsuaFl0I15Us3TNUM9sInaiLlylicsSGfc8qJD15RCOuNtqMHitZaCQRcgYmA+GFXAK8KXFRGt9g4emsGVKtSC3N2nODJb97OluSmnkLl6sGRn8Qmk73WFBPZyPKGXewA3ov+1pS9YqEZQp9E0MqQLtdb87WJTGAJmm5plVxK5nf/eKURnd5589aKVkyfeCFGvajDee7rQQGnuVWhoe7ga+A7hh0/TQumj1sP1Zjjevbkc3PbrFB4L5ghCbJzRO+1hnathlV/gcOPshztnxHaYGGlKYF2P1Xt4VBtVNfcnVN4dIM926154teI/8LEnUBqqf3IEJZHbEnH82WGipsDXVBP8oKQkbDirfqW0KDuvzSrkdkuaSO1LtTNAoxzAQJeQQXKns9CAfuDLlSVbRJH3mPDBTTjPBHJrH6wdwYp3y5ZDmPlvnnI651CA1lg+v+d7AmulkV8QYSZkOsdtuZu/grVUL6zJ7dJpOSn5I7Gn2CqPaHisEZmyi8d0Lgh6DeDbqjrdNg/REhlNrKzEH+iRwcUVN/JwnNbM8fFTuk5yWrKMGh+MeJBOFyWtp7x6XiP/SbHb/HuUkU3UH5DrosQrSYtS0ywSXlGPjQ3on6bTG40VSGPg7cRu2xbrxYMf+IuZ2wW6I0vvswzPKsoxg49J7vXq49Uo+JVpu2HQy/G3nMr8H/q93Hz51ThjvmveKAi/235XuLMeBLhHgL7Kn/WVUrASq9xSIP54u47OyRXMB1eFisqFvwP9ILGFCgJB407DpCJ8Fx8sdNA/HLJ865mlW1Z6oUdGbSPy4LGEgWdBBua4gBZlauMLkdNdaDYl8PiygIVJVa1op28Y3onZR4C2OV0Ag2qX/IrgCmv3NZ2PpbdqLQLwTKnsQp13uyR+QikNjY9qI7FPJ2mvxozHiYgxCc7wOZFEk1UrjwIwZqZYYdAjI6UrBpu7clI0076Cg2qe2YE46gadSWS/2pvIvqH3aBe8fscWwVgUzI10WAVhT98/GvE9BxUFS/JIfhuolNRHtz1AM/7nSRYnJVtYP2iqxkxvu+GPFlTAaUASa9E7HWlW1ERcVtIEdkkeDO61pfyzu3bMfe8Gmsd6uwt2ubc97/3kzDtQPmGjAXCpL2tcvFyrTdLEjqlstj+8Bn5B/9aLgGi9QDtnmpKBqgN/defLY7Rgj0ZfVJmF8l2GX6LMLu0zyHPo1BHL0+OFJnHqkKtZct4jI/1QDh9GENr9J+5aSuZNCQ0ex0OV2Taw3yjlabF5zl54TcrGAYMsft09Rmrqk2d9DAJHXITKv1IBcM0mv0Fmd3Kft12RavqFQOvA2BquqQ/KTIAHFfqmEjWamM0sCUqkExBcgto8Wdzf91h1etHQEBPE5DD5pryvcb0HNSsY8qEKGen/PqyI9HvEBOhqSnIl24Q3QuwQsfkQ+QGWus4WAe94E+TfCJenRqrlkxhQh17dNomjT908X2WueAvLW3VirForgXab0ZsW0FZX7c4g/4NLOfcw4TPn52PWGh+jH7N0zU8qygMgiqjZGxMD+XwvcUMc7BDtPtxmCrRFXLErss+V1wkCj26llRiw+DhQGxfIETXEdInF998yuZNl8bC7lwDuSnW4BAyW6cO5RdF1zW1DLNsQl+uGTro6oGQTxr6ua9OVjpLdOC+JwupBpa+pG3UYmxan5Y60F6yxqGk3iZm84agoOYaD4dutUG3Q9OIcRTTk87hzx9LdgFdr9R9Rjfj50t7QvUSWm4ZD42fPh/J60gerd5vDWTHq8+QMvIVwZ/lyPb7JdlqEaLClmIpnK+tVQ2DLv9NOov+VwOADI3gT8QaN+BZWiFiLd9HscDMUcE3CUD5ohAl86UG42lEeKA/9t4cQqs0RoWbqTJLxJ70C2TK3Pj8deQgR9oda3NEaIuI899vrSMlxDspedabhOm+KqgOOzlov9A0A37OCklp+38+VIIb3MwUtA3ZDaUbf7L2e8WcciAm2iGV71tUIOlbHfKkzgLk/GCpruoMYBwhPn3f+6KCLWk3D/jjEsO6B3WZdLBlLyphUJklLT5o+3+YBxsF3E7aG8PruldgFaEmGTqdL5vL8A56/QzmXx47i58C8kXURWBikRsutxIj5hCK2XWgT+N+xLn0HpJo3CMRNZx7MuWFgEe6yKvmZ/qxjfrnGKm280Bdf8HXXjNIMS6ajDcf1ubH0V33Ah2mXYG/FDY4zGlavVBH75YcQJ37/c5i+63sKZCLzjRSZyRmS4dufuEs4bWdVsIPkILFkDg8mz2bGCMOnuPSHBZVTxIt2YZ2oJjQryMPqSuIVfv/nHF7VrHi5LGWXtFPe+Es6pCDuD2DUeOJ2brg+jsiM30r1I2sIamSHcOaUoglJd37DPi93QSfGtreA+YOsDiJp1rVw3dAa0CW0WOXxSASkcU41uhZEfpYOdUbSJej/2InYfv0dW74zXWcvWsMiSbDEfzHjPtbaXgG322orR0OUMHMIwrkMDgkwp2SWk1RVS3OJc79ezBnEqWcA8fYBNOSq9e1HIC4KFlu6iv+7zMApyIXxpCiJrjhignzWU/2z1PV21CTqL6gp9Nxkl5WZHITyh/sAMbogVcYOm19IW12FtJ51xhHFiwOmqebMlMwojz8I51EnN5JJ6gvYxRKbNpPVfxWMLVY8J0OPdsQBhq3BdJugP6Rlau2Kh6StR3gJh/5TZ23Rb4VfnPEfveQIRavXOYF9699yPJehQrfQh1A9slEdKXij+DI4+5g6GwadicPL2Ti8C0iaPc452je8IUsxzQFvljrshI8Jk/6/PPM/7G6go7LwlBMAWYHWMdzmMcw5RO43jWPHkrqj8HwN4ENIn2yg42GI/ay17+Q+Pm7cMc2GfeLHTvCsmV2f1ptLQziuHLE+mm1idpNAqOyPDWtMMMbqBY+daDE+VvnVyqLhpLA6WS80z5FsJEhk2AaXYxa2gzi3V3EMpOCFSOzCvPJPbltbtjt1NoglQ70EleeA5HtrJV5slY0/PaFJBho3kUTnFe3fbspwPfFXgXV51r9JE8y021cKV8Tl0vejdlPlaAagmaPwNz1wT5jRVXci77FjsxjSoW8JuS+horXNdl/2X7Gd7Srk4ubp8YKCZe0Z0Y/ChBWrIs9JBbCkh7K2KV4+YKn/+kNYA4jBaogstE0YmX2QUUJ9FM0t9si+1SEBefNzNiaI3HQkhavlcv7sZQCgs5pue5wmZLj4r2W+1r2CvY6dkAKiVMqS5MGeawoK7BpPf7C+K0wE+yyceQffPCggPbVM91ZW6s5J+aw02AFAGM8d3SoYMPWnwz7/eTYS+gaHPQC9cfLpJD5h4+VMr5k1UIKrsUCvIS1SM1Vs9D0UX5g22gRKx0NzTlv7xgb1tcksg5I/1uguDtfovUrg1jLEY3s66GcbGUyBfCROzBxHU05cFOPBB7Huqmy9yuxLvYq5SYZGKByj5l05kr9BHXMNOZuHHWFZvLNNQGsbYNsZOluOJOoSeLqOqJ9Rl1yWlSz21kHSYJjXXK3rU0qSIHs/MipB/F8x3mm7V7sOE9Q/jXMJadrCxokdKDP4IvHJhULSuPaFaPnqc+5/oexinWDQrbgP2GA3HqPeBrm0LSohbIY20A0g7byX8oSXO3jl+H3/8hp8SFCU6Dk0r3qm03znJEazEHZj6hO/YNZz3faFBP24eutz+26oiLFlZ7AuGX/kydi17GG5+GIVPtLTYEogyQ+/EnZmhg+xkToZG9YWitjoc8IOj0mSel7rGToiwtbjbJf/L0p+vB36XX3CkpNyPHrRrvIU5ka/stTXiVVVW5X2TluzeLa+Krfn/BfSAXoO24WMr4p/teTIypQEWn/EA2Mb/mWujVhH7IiIwGEQ0PAnGOtNPBZzvmNFctzZZxg3MNgXuZsgV9giX4jSs+xVH2S8zEDrgoqf7Md7Tyw7fp5hIgODIvxA8w5ABXXHj6cxzbHfTVla/cnnWI5kZtrGgXcCIP72M8+TUV3cNO16tT/Td+yavNEUA+WxGeEQEXC/1t0351yfWcW6YBMHnMz8uzN5y5aHUsPBngboruLNozLWwRwUMzh+cJ/ceSPByDWXf/jrpNPJ4kYl3+ePy0y3u1GY+55xCD28xrneXq31Rzyh277UkAd6SxDjysxS8O/0T1hJQ5qBK+Qndry/QFz2Fruhggr/81/SgmdKcjUDcYw45WTCiByb9NtfftPCj02rK8AQffGW0qThNeIuFg25s233MU1npNtKJHRdolkpQBgfXu7R+oTbpDRwLZGiNX7LEX7KEJw+FClYzYlQrTffs+a0ggf+CpgCl0igPeGnb2yNgphYQ9lJfd85u4SQSx0ldY2jvb4vkDrg2QF2hXnZKKTgdY1KE60IEjptpgzGe1g3SRRrs/vgDSS3sSaO9xfySqrL3ZyH/Ch16XYkcGU5LaqPJ0M9RpljiMqcENHx4S7dmhtxi3vynGweNEV7RYMGL/0538lRf6+mL1tR70oBRXTANKQSJGMtz7YmK2Zf3ej8PHP0uSOdr30EtbWb1dp0GP5MpcpFs8FIqTzLlOw+G0LC0UOyLVgFVll12HJ/ncchnSMjk2LM+h34P882qwI5G0DiycAGy7sRL6Rw4mR1aKweCUgl6ls+iehg0tgehkktr1TeuEiFyRW/5yRqaZwisQOQur+4TptQNFXb1nXWxfL/2DZJ542HDjF4TnAGSXX59G4iN90HBL9UrX/o3l0vvfuqeG8oETyjGptJkV9RgNdcXfgIEqu/xuUkZBymbqflWopaCh3brS6JB4q4Ewd+6enDKwg9HelprdgIeD41oJewxTnNbQId5pNlhFpBznuuC+VTO5Y/n+qkV/s6ZLsj9/ZbRojOBjwkjlCisYM7TAWuTtaWohluyMzo08sb+iFp20MEVQp//C6FfV96Sd/MigbA5CxHzswlZusjOwfYur7uMuHLiICprsRuuDfjEqPytixP+qtKk6+MhvMeO8L/uylLQav3GMwlJswkOuF8Tj0cOgQigfIt1LPle18mlaDc3nyYw5mLdN+Bbd9lTeBJTAhy9VD/clu42A4YX/2IU3OoRfUenGFS7BuiWIvKcptqmCg2BR0m9Wn+U20OXvf0rMvOObVXXOkIdQBiIyn7TzXORkGzIrusORlgmmnjp7ouMQTqPXwesTgFIkQlaP+yWHcI9Pu9XEgjZAComRrWkNOhlkvuEFHhbL7iA5C3kzOz0Q8rw0izSEsvN9bROwOolwiO9gKT5eu7TpVzejqHK30v2Mh6RvpdTrqjo5v2vvfR8gKQf40Mq6Es3QraC1FMi6qsIB7oW11oR6N3MmTwF1us4cGzsOxboB5NzW3vLlmAPLnKuvbigh5XI71x0S2RwPuK4eSoqVHSadJqcFB+0kMzEN+ldFHoMN9bxFqAZ7tgp1MCrM335TKJhHyt29qY5SZZJ8wq9/okopiEB6hQT4wzcUEtyU4TEVy6oUuhT8nnNupWgbhiyW6/PrMd5XcTMDSeeA+QjC/0wiCEHRvBtci7kLrMJElXzK4W/vfh0aks/vyZZfWl6SrYeMgyIR9CqTVHFDquyqWuuIYbKqAkiqvQcJgyWacdyJSnYNnLHIMi6LYln9Bzpkg5v3kIlNmEk7ChVvkSABE+V2vNUXplbI2nA9Uqe6wd/o/Xac7VNWADOEJS1kHYkVC/KtrHSyfzYVnU4Iybt6v+TBzT0PgGlIwWHWeXb5+ffjjzn05YeeHNDlLvCIFxvz2c70+YgY3Q+/425isSV9ZwxulLxPXrGulBuHhLBv1DnkKTolhrBnc57C9CaGTXfuQcPoJcbTDxGkT/SHZ6sHf7AI4mvvEcHrNyesBkStFfr3M4pi/uTeTO8bYb2O/106Bgzo52kwcRxNBVt7ZDmOfYvtr3v0ADFqQfUvwdn8W7jSLJsCEdhAs7P3a+U7leHCvb38eYG+CxqoMZjuk3tQ7S/BmJ2m0CzyrM9lFADmJhMVy2Pm1TDtUzN3Gz2ouu+TJ8TuO16MhIvT2NE3fCC5c7Xh9NnSTNmcjl2pUY/9p1mraz5CXfbb5P4W8ZRymcRoueTtFzhJMjqNISeamLfqDi3o92xL3pIv2LayjixkIdcsXzsXzWJJitku/m3KrnKiCLTd3LMzE64os3ch/d0+KnH4DRlJVQDFkx82AtOR19FuhixGnS/PoSq4j5UT/LSJhzvv5okjWK3v03qm6mppwjEcwcGmMFmUoyhjBmpjDqg7gE5Tk5lTRw2SIVsWUqHXNQCsmS5fPJ6LcMUD7imLzYo/+yHofNtIYAY+6tB+x60wF0oTj8f38GzCGUKcIq1kRQE+m/jkK6egWPOxZLhPKCj9cQ4vZ6uBjlP1zBXeA56oNYdZX5ZLOwbFskjUnAhkZUmGpJuf+dpu5GEVGv/YMVlU+p2C2XjxvpmFjm4kkJk90PO1jE0N7KnVWVmVNPXxW7DQ+LXlS1N79REuCB2mL/sYskMRMwLjgQfCGHjvpe3EoUU+tvNFZw7H0QGyd/KMvxd6cc9OgIUMCUoDOEYVLnUK5KOR7sU28urcPWgAfMZ51dIsswwZyDz+Hvrf4GPaUT3bqPmhhCRc1cGANU0N6Zm3ab//nv8RexxRv9nm7jLZgLseksVRUxr8kwNblYfIpFyIFTY22JjdYv5fT2m+5GS84w3fQL+lj1z71I+DjkI4twUmK9c23ckmJqSpTBlJMkJJ+Vje664Wy+snKYo3oZCvEJsgf5YriW2WSj4sTKddh4hHtFB2sou48cMgMnkevqSRRtoXHVCdwMsMeP+lBrjH7WGIaa3A7DVEvpkLBK8rWidbOK0+rDmys0eFnl1eAYt42+/7lQ0UJXozRzcSfhhQ2XN5Rw6fILm33MjqjemTUKPMR3MwX7vH1q8kz1yeUvS8f/XMTictkrxHDRfkxys7C0dDK6JnhuVALAO2nQGyIGoB/joy2t915AeRU8RwPz0IqT0fTc51uXvQbLmlUyHJJwnI3AV5hKDkrEdam7J+5wfJQV+EbFF0hy+Q6Es7GkJkFoIKaC/3Xm6HQhZhXZUyjLKKWho42TA7w7lkRFn6LQCzNtmgoh5TsPyjzr5PnIFyYM6GPzxGare6jk+8U4PTqlypzjStiEI8TwxG9ggXH1vVPobXpjVR92figxhIC7YdR9lL6e2Erw9tekvyQuRVUSaTEOxOFjyVMMbYINHNuWTz5sEZ3t1Lyy5JpaOl1dNhpqFhtpRQSzDoNuVbgfqDRrQ5n6TPkP+Vj2Iu3BWSYbntjfyEnB3KM1TNFqjAZI1syD4WCkzu5dvCPjBNRJ48wGQklmeas64mToopg3ehHeCVXKwL3nqtoE3dk+OXoCNurumEQyJtgGq5Et8N+kaWUjatI6uJ6x3DnxOLtrynhP+7wRBYmYEWT86eHEN6Yc6f8prj1eRUe6dyQZh9spZdGcU/TmzlrEE5XcEX3EJVb2ik9J3U2DtbN9mgrJYel6N1C8TBJCzDvYNDOI0OaBrBmB2EJ7B1Y1iJhwEHRs6nVDWMytQa9QxIjCaMYQqZYcHK44iNVUhCDZK6pgckCnXqJf7z+KRewqG44Jv2AUoca9XyKpKbLHfpS2viaPjo2TDBkbL/GLkeeCH75moAovHO7MMOBSfFpfaglCqrMvCbyUSs5o6/gXZgs6InAjPxhoDbW6NUbLxTGtiiRA1/UFMIFh84bBNlPYwi4IwdtXHXdMpMiKx0uDx7Fjef4O6H4JJ54JV6NaqDFSm5I7Ez9qSVKthx0VOO3y3+sFHBZlkWozqFDWGSC8AO30xJMURMTEUv76+lJ7I0yjnp+S0pDiKU2Kt5gJCWjEe6dBcBS/RUORVV/rcWC1V2TvudFJo3C7n4OaxHS7Vlovi1fVtXDhZXeFXtgRRY1rCQJSWZEvZNn1Ik0VqaIig7fRdKoUCUjbc+cJ9e2bVIzrmph5LuyDfYT63YrwyjK2vfxBOlPczJ9Hts8FyYqHRsPgZKTiEyaxHQaDkngxHKgDUfCIiqu8tveROpjXFrKg+mlkisCZ2XmBCAAGcfJ+A5UON1b+/GELQQJKor2hThdxkKsbjnxENLrG+8K9X+iGe+3trrdmE9RspxPFcDRlTKD9sbrwCOJzF8qJ42oGctZe9vEYR1SOxBie2kCc9iNT36dpcW+cwl08eTun40qIwJSeaSqO4c53L2P6A6DTqD3RH4RSTsjhgK67GUYlSbo9qICB8zOalq9fQV/GBVXOqfxeH5FdTqskgvHPvgFYNG1Di1Nd/azRIUuJ7DcfzbtsezHmYeoXYiRwCJsAHafFwvf+DSrITr0p+8HZbHYSrNwmQxFIgorD5tQujNOhlL0AVo0OEiS7d5tN0QXjKsw9wqDwKouuOFT8jNHRiefFgWR+nuX5rH3x9HQabagLg+HnNCOvl1rvpP7Oe7oLtSObopfVsyQasHg+bg+UmJoJob2sLSzBQd7u7eC0lYbXEhyWzreSTqSttcUrtP8fB5Yu8jx4QdI8p2jMy6VTYLhYK3/2PP84JjdAkxzP0sgDaw79WQTtksIQZvtKBV3xtbFQiHL4lz9UO3jcJ42wAqVKTh1OHMb1YMz6WHkMrsW0wfCNEPxNpNcl3FvjVKpDtwkc6dfhZhzAfbLBqbgK5ypJJUi49YovzLCjjTv2dy9SRztlZd+JqHuOpyjgaXJZbUz0+oJkUe1G9Ne+S4lZUR/gGsWsXK7NhpVoN9C7pxuU7l0W55wwvVo1IsKjsmfpcV+Xp1lc8NGb0DRpUVOhQ2ss16DjyDazdZORbAd+zKFRcyFjXPIeiBScB3Y1oaVfYMhbEgJkqDtcIeMWxzEZp9Uz1a3zYRSXZaNyPHj0VYjEASR0UJ621pAGV5VtTXZS2+MtwbLMcHMgdSvtQtWc4idVB3XPQhZNBpJwyVEj9TFnKL28bsiKOo9Gka3up95sZbOZlXnDGN0zuMiMDXv4Dvp8or5wGxhpyOt58SFt/iFWF/KmJCS4tKMbUq+S7nIMjUKEpGxhO/0iWiq8mw9gRP96k6/e+vAV/ZfDGhSiMYojMjmaHoCa/Wt9AnigN/R6/4tjN3OTHGcUWmauMUQkRj1NccJsJ6DElE8+rbnZQ97DWXlnzRxVxWkmx0WGVIOoRkc3ZSu6gkK5V4lWARlBnnADdd9Axu09PZGw7OsPeDI1TWhc3Da51LsRatNbRda61c/ncOAUFpAio3mHX5IPWCIJGwy0E6fb0nHNQ07gpP6C/NUfS4efxt1z2Wr5JG0QFszbKpmFZRyvNhush65Adnf501A41B2NVxKoVpCq7KsgmujDk90zIsNDXel0z8vipZPk+g28O2JNSZpzjlg4DlXf6U6DpdvAmFhEllKIYa6KyYjUinuEdW/O48dzSuhtn4BFFAtK+8JSJmPfwC8IC0lXUBCu5K4phttBGs/cQV69Kn1Gxy6idyUDTApGFgibo0iWC6OITMSFW5b+Vc+VxGbGtCuHaj1kK4iXi9gTOV8UHssT5ZzPeBqubCiFwstIBEr5ZLlPmxxyMKBevPJNwqHmaR/FAQ2/fDBerXjpAC7WifgBn3e10YS+DJD8zd1GRx/8cz0NV9vi3ru7Jri6Q7zk4yJscjNQtEytzXX9S8rSJAJj+xke348sMXAmzuFdpO7v3+OP+Zp/HTY1sy9BOKjKnIys4lmLlMomaWqKZ1m8rrpfo6gFEx/v/ofQHSvyLI1E2lyYi8GdNXajI7HuxQSmnPYFtN7LPw8H/e6wbduMwzdbKxJ/Er5h3XNWikCIY7b3zo3OTSrBDynSvKs/RXccZouWy39G2TcKpMb8AQyt/5jC5HLzLTy24yGtXSr6RF+Kr3W+gWOvN4Xhfo6rMeHEAv+bJUzju1Fgdv2t7k1NWasn+yohJxKUIlDgvnfMgsP6mgaeT5cfxXMRVGNV92u3cfAfvXOZHt+E3MPtCuEuPxwUZUkQmTu2V1p9RVk7gk35l+WM+Nj5WreYmEHPqIgtyB10i0S9r7ttcpenvZJ84Z/mPr+7qUKPXg8sLeK5H4WpMbmbFXNeayrOVERqX2mpU8IhIMSsmrcp52+3Vs2VHx1qLD6Z7JZ9bYkGJ2ZpSZyXZ18HgzJBIAh2fmHvLb6TDzcckKKymqGyM5bIuf+D1ieNcrW0qQJ/fEYP0owLfQBy4Ngt8R0pHoT2YhQ+aOIdXbbTwp4Yw72X4inYvAKokevAVyFK3bK8gTvI6CAfxRDIhpZNdIAix+YrS7CJCfL6Bj8H11zkiupLHGXjfg9Wfra2uDh5n8UTFUZ+Ms+VPoUXi+35EsLhjmC6NNn8qZKIhJiU2OIOzUNXC6BK0D4yKMt8rqD8Dm/J5+YR2XFlZXnIhdOnzk8Sm4mxY2IFDuxZIBajg1v2yhrvBYwiMO+EjiIxsu2lDr8N/qCGHa2hplMFXtH409IEaoIWeo+IvtkBP/iWLCinIaRSEZ9sYT5kEjvbjiUb6i2bjO3sDN4x9l3Zr7s+UhAHjGgI+GAOJlKQFm2P6MtD8d12PbGRxYpjxg6vu7fMhRJ1NsCc7T9Erl5ZMnE/ECCA4hBmZE0O98iJJuQtV6v3+Hf80v79e7CgB/l8BqzKXbMuFVg4fl9QpeKcYKCAHNlFYkQ0z/Ec9hUak0TAIE08SJW7AmECvDvG5p3nJ9+F0UcWcYTaNGNZFdhPYvn1ye5BRUvt5309zPfGWYIv+ysZrkRN/BNEaKHjwAaoIi0kJpXgLvwEnyy0vGVRRxFoRwfC7WyS5wnAQK/caBUu1ZH4v8fjB2dC4WWBCddlaXOpVLChadDGkr29bMUYbVQRGNiugVXpQp7MZK4BGDKZPBD8rTfTh+AdUarSd8Jt3s4j9HkH2tZ/BbAcu8l/M8V3l5h3xRYuCW8aW6shAig4Hk4hpF/Eht1x8kfaqIWVkk6ib9IWgxRmMg6OMM2NwxmURfuC8L+fye6jdeAxe3IC/cLKA/dp2QQQ4cCtV3o78ymk8koFyw79EuuOZP0/tDh0gXts8zWdzAL2qahAQ2eE2lNpI7uWZZ5w2YGk154IU5XbEmL7k2muE0I5Ad1wsqLKJLVjg/EPbf6rPkrgJYS3ieVojTF3ZmLvNleiKoleWVdPb9rfx7HhByl88pSZaGHogbRXzjKYjVb+Ayw35UVmnpq6V317xpnG05PfY6T4jU2nvG+K0nElMxVg+7yUzQCsDZxU6YtE1yz7Et8Zg3Zbj0jXzQDhOmLQNyLF4hc45cKS51yASWDPnNZ2KlIrTacqxjqWmk7Rs3fHnTqqombjK8obcm+K8ZIdJGpHltZQz0fMawAawT283Ifsqzz2ou5u75N5MHd1TFURv/6cv7qDbypnawjIPX9B2nPNu4nztiHowXKFJUY2IkqjEbtVl0zcEX0hsm8HkLoLYY5nUt+Z91cNOuyEQ+D1vQabSLu/aJfDRK+2GuU23/8oJgRknaUpS3H2LCQCKZqfdeZjlKJ7NPu6sJoSihWtf9heWk2C5nC8ZrL74/OmrJDUQ/6DYrbSUmmMV/h25chAffgqBDx/v9I8m19y0XOm5Kx27tBHUqqav7Md/fZDqWOwGBMYDdPPA23aIjmF9MfEJQIcRnSxBHPlGMZ6s5AbNBcKuqjBXNTvj/fwy83yRkU1/7hkY/BJHMPkKjJwxrpUkQQ6+RCr695FFATiPWoemxjhC2XpYWf9zZdTZlTedurASrghIQhUe5bkx7uYuiYMNO/BwF86LEVOC+ZsKqjV3ClPMgDLGxpUHI+h42hQH+ydMB8xHQyo0lmBaOWhYcQ77k3+BgOTX/68nWclQRrtWYCa71Wa6G5iZLrov/+OMXDQn9Y1DUAl5fn76aC+1BxyEiAWmazmi2CIGiY8Db4o94BgK6BqvcnYAPD32VXeVP1pANQO4Swr9/YBcIjXpltTLfUopVW8JvAW1IuHCtF8DKIZgc+vfqzibNz0T8qavB4jIoLwHDqoz12k2zMFuh4VhMg/ojToImJA83LvwGBn/rnThibymrARBeEpVrivMObINFkK/pAn4jzV0+KMDEUwJ5ljL0vuLqSfEtUBJPkZhUIFkfPM/rIGa/hrn7QZlN4nms2f3/iWom/hPzPC/g4z+RH7on8Tb7PLnXMEGyayrG5TKPKz26mEcTvRADmXeB4yASDrENnbBZo0s2pWkCT5QA6leIFS/Niz1O6R5QuTpUPQuvoiW4PDUTG1f4tzTCljUM6sacjuNkoqUWWZxy7U4GFvVthWBGcPbMGbM1tyrlnhUi+8suato+VvXxoQJN+3wb18cZn+hm+vVdocJ0zae0ZEiXGjcnd/sW3XwR7IV8rX79AsFxAYkKqBDcTW2GG9b9jpKcgpAJmgfb36CrKyf18QaO8TVGSNT/YKX0XMZgLFc85yR1Tnvolcg0Z5xFmdridrB6gU5nIBxQ+EPnWJJkFDftJpBx4YbmsVHjAZxecLa9YrffOjDbNZganTW/wylmR8Q8wp/OoCo7nA5ItHsZjkzfLjlxOjPhwvvQxwRK2xaCYw67DXoU1WL5JritPM8quCeRz8/3N7/m6r7Z8YasV4Nl76ku+8cAJv37FoN1FfkDELKTylDjsfUqgjCYcZq3KoE15l/CDzinmMxShDfMzdkqPCeeMG6AQfCq/wTz0fkVnvkNc1x7QYTjMvxShYq1zKNzNOfsbVqOmMLcmVgplo1gbA0qbmXbjZD+FbfpbjE+FwPbsxKb39qT2RD59y07Uo6uBtttuRAENlfMYCibK/TFewNj5CgJWgAq4pk3kDRHWtGYiwKrzxY7yf5CiUI0wqelSFjGnSfiQ2lyqvmO1LMWg1WKXfnubJqNzVLTN8EpcdiSdcM4of9ZHTcrl8yTlChYUCgr3o6L21QQovftVpAtx/MCx79RwdPePtUyXoYQJ4BAjf00vjCaCIZIYBKom+0sLIm/NTK81m9TF0MndEQquJnRPWRFj6w4DwJJCpuGn+IE24gcnt0Rcx1bHoZ1vEGQCwru9JKaqBMaQLkU9QlApS7kuiXaFEldy289QOcrZ1FQYy/bA2CP20POxi9EeqV4vsMIwIEkctPwgTOg57qUCObs7aEq0Suk/4RB8JAPCftq2kJ6EJlb/bOORTteRqubFhY6OUgY8fV+69CYm9UN2SkQt+nReah9/nr7MEwnBnoZlXd5mlPO8lMZJv0VzuV0gahazEUmbbuYNp8cste4CkFIn3zPowSCJ6KfbTdCGOF8TglQ5cEbBD0pZSvoAbTk9XqLOuhGg+39uwbqLT9KamwMD1Siiy/oQMrvdi3xwq0Sm7XVYEttfMNkB3KzSSj7Jq7k1lLBTRnPArYeks3cQjm2ysa1IUuDF8AUQ9fcVxYUKn0ZZJI6jAcUw13IDs55D6ecXiupczd4gAVhpTUTY/bZMzqdiHeo0D5Gq2hSNAh8ofYmMHdpC82orVP8vLEO7G3gCnG7stylzmMCjzs5VTvm6u5/h3lOYR85xr3aXZv2rR1xhHSgr255ZODRJiMRrJSchgPPg2NF0MFe6xySQjhSFNSbvb4q3zAuuUAWR/zSQEGpzjLuPpFg8uCTKGE7UuGM2mZxn8AqjvTed1gx4WEBBGAh4u+IsLMEPkWu6TIwTFHqtVDZn2ntm5tIekR21mBjr6qXMGy6s7TqERabf1XncOG34Sr0GvPUHFOk0k/ZaOE/aV/wTW6JI4A3HawGJmpaZH+fapwQePakJh0F7qP/MmpPphuA/FmBWU8PjZJfR7nJb7K6aFaDBXkX0EpC5vWk=","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"a349b2a16820229804f5cce2c44134cc50d82ad7","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-622","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"1382e8398b0a592ec7f3d454b60c5c568f0e3a3b","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file diff --git a/02-SERVICES.md b/02-SERVICES.md index eab2645..aea9be9 100644 --- a/02-SERVICES.md +++ b/02-SERVICES.md @@ -26,6 +26,7 @@ Implements **real-time API approach** (no caching) proven by PteroSync. namespace Paymenter\Extensions\Others\DynamicPterodactyl\Services; +use App\Models\Extension; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\DB; @@ -37,8 +38,8 @@ class ResourceCalculationService public function __construct() { $config = $this->getExtensionConfig(); - $this->apiUrl = rtrim($config['pterodactyl_url'], '/'); - $this->apiKey = $config['pterodactyl_api_key']; + $this->apiUrl = rtrim($config['pterodactyl_url'] ?? '', '/'); + $this->apiKey = $config['pterodactyl_api_key'] ?? ''; } /** @@ -170,9 +171,7 @@ class ResourceCalculationService { $response = $this->pterodactylGet( "/api/application/locations/{$locationId}", - [ - 'include' => 'nodes,servers', - ] + ['include' => 'nodes,servers'] ); $nodesData = $this->requireRelationshipData($response, 'nodes'); @@ -184,16 +183,20 @@ class ResourceCalculationService if ($attributes['location_id'] !== $locationId) { throw new \RuntimeException('Pterodactyl API returned a node for an unexpected location.'); } + $this->rememberUniqueId($nodesById, $attributes['id'], 'included node'); $nodesById[$attributes['id']] = $attributes; } $serversByNode = []; + $serverIds = []; foreach ($serversData as $server) { $attributes = $this->requireServerAttributes($server); - if (! array_key_exists($attributes['node'], $nodesById)) { + $nodeId = $attributes['node']; + if (! array_key_exists($nodeId, $nodesById)) { throw new \RuntimeException('Pterodactyl API returned a server for an unknown included node.'); } - $serversByNode[$attributes['node']][] = $attributes; + $this->rememberUniqueId($serverIds, $attributes['id'], 'included server'); + $serversByNode[$nodeId][] = $attributes; } $nodes = []; @@ -206,13 +209,28 @@ class ResourceCalculationService return $nodes; } + + private function rememberUniqueId(array &$seen, int $id, string $resource): void + { + if (array_key_exists($id, $seen)) { + throw new \RuntimeException("Pterodactyl API returned a duplicate {$resource}."); + } + + $seen[$id] = true; + } - private function getPendingReservations(int $nodeId): array + private function getPendingReservations(int $nodeId, ?string $excludeReservationToken = null): array { - $result = DB::table('ptero_resource_reservations') + $query = DB::table('ptero_resource_reservations') ->where('node_id', $nodeId) ->where('status', 'pending') - ->where('expires_at', '>', now()) + ->where('expires_at', '>', now()); + + if ($excludeReservationToken !== null) { + $query->where('token', '!=', $excludeReservationToken); + } + + $result = $query ->selectRaw('COALESCE(SUM(memory), 0) as memory') ->selectRaw('COALESCE(SUM(cpu), 0) as cpu') ->selectRaw('COALESCE(SUM(disk), 0) as disk') @@ -227,17 +245,22 @@ class ResourceCalculationService private function getNodeLocation(int $nodeId): int { - $response = Http::withHeaders([ - 'Authorization' => 'Bearer ' . $this->apiKey, - 'Accept' => 'application/json', - ])->get("{$this->apiUrl}/api/application/nodes/{$nodeId}"); - - return $response->json('attributes.location_id'); + $data = $this->pterodactylGet("/api/application/nodes/{$nodeId}"); + $locationId = $data['attributes']['location_id'] ?? null; + if (! is_int($locationId)) { + throw new \RuntimeException("Pterodactyl node {$nodeId} response is missing location_id."); + } + + return $locationId; } private function getExtensionConfig(): array { - return \App\Helpers\ExtensionHelper::getConfig('Others', 'DynamicPterodactyl'); + return Extension::where('extension', 'DynamicPterodactyl') + ->first() + ?->settings + ->pluck('value', 'key') + ->toArray() ?? []; } } ``` diff --git a/PROGRESS.md b/PROGRESS.md index 88890cb..4c2e31d 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -77,7 +77,7 @@ All dp-NN backlog items are implemented. The active reconciliation is staged on ### This Session's Changes: 1. Preserved the dp-20 panel close-out without restoring obsolete deployment guidance. -2. Reconciled the location availability path to one `locations/{id}?include=nodes,servers` request and fail-closed capacity parsing, including duplicate node, server, and location identity rejection. +2. Reconciled the location availability path to one `locations/{id}?include=nodes,servers` request and fail-closed capacity parsing, including complete pagination accounting, integral resource values, and duplicate node, server, and location identity rejection. 3. Replaced caller-selected SQLite test paths with the internally generated `:temporary:` database workflow. 4. Migrated the retained Qoder page set to GitHub Wiki and synchronized API, deployment, and testing contracts. 5. Published draft PR #23 for exact-SHA review; Mutagen deployment remains paused. From 6b7f83bda6f7c3fe014d52428b31af1638daa6cc Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 22:35:26 +1000 Subject: [PATCH 24/95] fix: distinguish missing relationships --- Services/ResourceCalculationService.php | 25 +++++++++++++------ tests/Unit/ResourceCalculationServiceTest.php | 22 ++++++++++++++++ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index 8ceb6c1..f344fe2 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -504,21 +504,30 @@ private function requireLocationAttributes(mixed $payload): array private function requireRelationshipData(array $payload, string $relationship): array { $attributes = is_array($payload['attributes'] ?? null) ? $payload['attributes'] : []; - $relationships = is_array($attributes['relationships'] ?? null) - ? $attributes['relationships'] - : []; - $entry = is_array($relationships[$relationship] ?? null) - ? $relationships[$relationship] - : null; + if (! array_key_exists('relationships', $attributes)) { + throw new \RuntimeException(sprintf( + 'Pterodactyl API returned a missing %s relationship payload.', + $relationship + )); + } + + $relationships = $attributes['relationships']; + if (! is_array($relationships)) { + throw new \RuntimeException(sprintf( + 'Pterodactyl API returned an invalid %s relationship payload.', + $relationship + )); + } - if ($entry === null) { + if (! array_key_exists($relationship, $relationships)) { throw new \RuntimeException(sprintf( 'Pterodactyl API returned a missing %s relationship payload.', $relationship )); } - if (! is_array($entry['data'] ?? null)) { + $entry = $relationships[$relationship]; + if (! is_array($entry) || ! is_array($entry['data'] ?? null)) { throw new \RuntimeException(sprintf( 'Pterodactyl API returned an invalid %s relationship payload.', $relationship diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index da11d1e..de51ed0 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -498,6 +498,28 @@ public function test_snapshot_rejects_malformed_included_servers_relationship_wi } } + public function test_snapshot_rejects_malformed_included_servers_container_without_fallback(): void + { + $calls = 0; + $node = $this->nodeWithServersPayload(1, 1, 'Node 1', []); + $node['attributes']['relationships']['servers'] = 'not-an-array'; + + Http::fake($this->clusterSnapshotHttpFake( + $calls, + locations: [['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], + nodePages: [[$node]], + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('invalid servers relationship payload'); + + try { + $this->service->buildClusterSnapshot(); + } finally { + $this->assertSame(2, $calls); + } + } + public function test_snapshot_with_single_location_single_node(): void { $calls = 0; From 64c04ea4c371c0eeae7aeb5debcd499cda18e379 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 22:36:10 +1000 Subject: [PATCH 25/95] docs: refresh strict boundary anchors --- .../Service Layer Design/Resource Calculation Service.md | 2 +- .../en/content/Core Services/ResourceCalculationService.md | 4 ++-- .qoder/repowiki/en/meta/repowiki-metadata.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md index dd5b206..8bbb41e 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md @@ -245,7 +245,7 @@ Operational tips: **Section sources** - [ResourceCalculationService.php:157-195](file://Services/ResourceCalculationService.php#L157-L195) -- [ResourceCalculationService.php:487-622](file://Services/ResourceCalculationService.php#L487-L622) +- [ResourceCalculationService.php:487-631](file://Services/ResourceCalculationService.php#L487-L631) - [ResourceCalculationService.php:426-470](file://Services/ResourceCalculationService.php#L426-L470) - [ResourceCalculationServiceTest.php:53-139](file://tests/Unit/ResourceCalculationServiceTest.php#L53-L139) diff --git a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md index 0e4bbce..06caf82 100644 --- a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md +++ b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md @@ -111,7 +111,7 @@ RCS-->>Caller : Cluster snapshot or degraded snapshot - [ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) - [ResourceCalculationService.php:313-406](file://Services/ResourceCalculationService.php#L313-L406) - [ResourceCalculationService.php:407-486](file://Services/ResourceCalculationService.php#L407-L486) -- [ResourceCalculationService.php:487-622](file://Services/ResourceCalculationService.php#L487-L622) +- [ResourceCalculationService.php:487-631](file://Services/ResourceCalculationService.php#L487-L631) ## Detailed Component Analysis @@ -235,7 +235,7 @@ Integration with reservation system: **Section sources** - [ResourceCalculationService.php:359-391](file://Services/ResourceCalculationService.php#L359-L391) - [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) -- [ResourceCalculationService.php:487-622](file://Services/ResourceCalculationService.php#L487-L622) +- [ResourceCalculationService.php:487-631](file://Services/ResourceCalculationService.php#L487-L631) - [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) ### Class diagram diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 7023c1e..768dcd8 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-622","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted:qkTEybd9tQzuDstX5IzR1CXs/trJv2Qp8kaORmGdEsjOxLytJAqUuHjP06XJn9y+iXOi9CHh5MccEBo3czEUCbEI3xi3jI2FX0U5Hb1shR6LDZa4SKyGHNVixTBNySA00Nc7Lz+raBGyJ9EnF9lGDKWB1J0M+K73LX1rF7N3R69cErBcAhuvCBd69rsyUTTKSXgEpXu6a6WBUCYLToWdn12p9VWVvjTtcSe6lRUrzgs90/zIfQVq9RYyW/9LbF/T1JjqYM0NGvS+uZhPFi3p2U9QVLIuGWoSFWeMUW7i/mctoN1NLGsU3TIOSauX990uB8YSEC+j3CLEU0RFn/c5OsWoAXtfngYrjb4AGHl2NEDSkwlciQRkxkMYxFEZyYcHT8Gpy9mvFvx8bbUg0Pz6UsIgth+Wt8ksCwhqUfDKRSDFIXTTfvORPKTzfkyLwlHIqFcgDPVkG6zJI8I05IjUlXG5jKJQFuSvTIn3yJqmp7ZhvKQoeYLzB31v5M+ZOkDLxB20IFzyEJJaajhK2ne42xddTRga+uACLExPlaXQ2RJgP7aEh4BxFflfEZTJ34EAFDODWNpg+cS/h15EWTsUaCG4uC1kiMBrOd2ozslPb/B4Edh29LEeX6942jquAGPtDbui9o80AA5R7YrXIWL0yCvKlGIvVQkiQRQKUdaVYNvT3BlqJ9Ka2WMvnXeD93o7uFgQDqkb92et5LlCLAyZL2hhn/HVQ2au4V4WnXgjVYGwqLpihYFplV2o6Ul5PDnwJGD69mAO7aSGG4TBaz1vo7thcxfYaEN8buhL/QRsNVzwqTeN25dxKdYd+zBxU36BMRYfjftV5aUHpmuuyJJkM5VRKQ6BjVw6woeWtQG8FgIoVUuFHpxorMTccI2C1mpkmzgRNMXQ85uoPlKkLHfbtEhYmKBBI5pISQM9VE6ya4qmYS3ZcA4Gby+GuS+2myO7b+pIgX6Gq8Edw5WSPn2Ei//99pnHyVX5UPawG98jbNRlrQs2TtcrBTUT98D4BYcMA+ktxGDZix3F4RcLx5/elIhe124f8f7S+X8phIq7uGTw+ZxP8gQsdLdGaOoF3tin+ZOK0iHk3oIa+E7zaPMUeNmQcixZRtKa4oIeo6dr4zHVltAOiLtV52OQDsPPCU8HwUO9GFXeTYlUMXhErji/Bg7K2iw712B/4pQW0+0M4atRKpXUCf0AstnGoCz8LlV+hEsMY8AS+k7jCk4TW4pv758c4geH+8hGXMLUSEdVybYs2P4Vk4c8nAaIEP6jWukiDhIps/dyb8RExWg5BKcfGJZXTWi3TBQKnGIqc1JgXXJUAOfGwP87PHb9WxxWsvl+13KF6/JUV2RuX8NWSAmST2z9I5whzQnfem7CCc2i5yO6yqpJbPOt+hpYlqFYp/yd6gkodn84E4+o9G2F9NamhIk1rCcqX0YoYhYX3he3rU49QIUaNev/DsEKQc3s+K3yH3L969uk8nvcFIDEREP3Ke/07RicsySihmrgxJ98Ld4lr2V25uD69/exLybGUdn2dDcVBUfI6jWrwipyYCInTV+f2WDOy/ki/Kv/G4WbDZhIXn006l1s0GcFML1GXUTxXmJY0ku4dOxbpkSooJ7fw4n3y6hHWfG8HpJT6bxgFd00CbYoe/b0gzXvAaWW8vpkN1sYSWr1kqeYKUzdSIW57T/K/LOKTHdgZA+L0R1R8CEvL/ecL3GkHaFg+gEYwMpDWhf5rCtDxKebVIATR9aw07hbWczXdZwkDXJlVd5V5vdgORzxjfzO/OFC44ruOlxQSlTZLyulYQFp9dHxHnHSP0L24zQXaZKtefy8cnmOapkooReZ+wZRWiAb7fxmo9D1teGxlOU66NKDFzhuXbd+HpEiPqGRF9y08wPLPou9goHOa/JMQmjgWBUVuQuDbR+a74MSWaZCcIwojBJ/uBzCR1IFP2H+BJDuKSrdeLDMuW5EJu5KRZ0B7R+zFnwOxiZ9EYJTIFO4DXNRb9ZL4JZaZJDqwUUgBM8pWHec/4cM+iRi7hh+rkEMQRAMyGpem2L+oSpr2mWWzpe8wQhlaZeVV2sbybXQ/c1TEtK34eA4FlFqimXo12UKrmimZi1mkAyuF98LXH1wCLNXeJVLWZOMKrSl17JGy+Rgsx9dEnAmdAOt/ePsBXXphzaiSY+6GMqmtIINfcgpsvFLf7VhdP0yeZ+kkaT7kJ6yYu+EvJqw32jYBjw3cBy03f0wLMX/dMHo6VPVsef8AiKqBBoTxb2uWBbY31nXY9EQgRoYajhQYdmKkqEJWTkgXQTwQDHnUdrR69KAqK1wYfDX38GDERT9ibC6fXsUZGq+QgGm8VZHTsFTnVWZUi9EUCA1oH4p8NtjCRKQE1dUmCiF/sMRKwCgiHZ+WmKV4ixhHV51T5RAHQ1fkcqc+hPFcd9uEqHPrwvlORQ9jh5rDbFRNCijsw17TiHm3NlZIZ6TOhCPiPO7135f1/4QfMvhj8NftvFreT17bU7G6ZhUQAvh6EcXhWZ2LDqZR6Buji6hu1u+6WgCFFNo+TSLl+h0xhKxqKlA0H4FQImLcJdXn4MBTrmQhqMe5H1iyxIN8bhT42s42eS/2IJqrvjiLVVNiU9DbRlYBe5TsLfZuC9GQsWYHdHB2KAAAceRlYBlwnnnVPexQl67P/G9sMfPJkJP7aduEQc+ikG8og1weDdx5GYauM8O/D1cxi8/7lTsEtDIGXuCC5OOHBs7utoXRrzgtS/D2kgNytqDqSaHVKaNy8NDlNMYbjHbsr4ffxNCRN6Pv2NPi1RODmwAvliw6D7KLOfoqACJKyBasvMnWyR24InlREQefIeRrWJ37pr9Vq55Q3FhvhZAc8rPO+f3plstLlPFQuqz9RWznCe1tPE0niOz5NHBZI9lhIv8cOJgZRzQJnMNAIPVderB7zfqLtTAiq8aipiVreV2y2vrLz0b9lyC8yWPsQK3aseiv9yw6i9ehl4z/sHroeApfLHdyEscUVNJXOvapP2qTfZ9jk4hocuqydv/duI2D65jyGlk6QuIPkjjMcJ8zaFur7eFq177IRSKIy0XT5XPXjUFSsnXp0ChOnfbgKyNvD71SvzQT7GwZI6hAH67jxNZKymIWPsLwAFOl+M5XOs8X9EnYbxKTReoFUvgerc0IprGMeJ16tH14Yd0i/HHak13ShbBkqSOrBhhWBRCCGt73qsgdMPKqQaZAihM6hzVtV0uacQePDcxX005Zjorr5rGsmt6BTBWli/TnwDZB3Ttch1RUd2LJTCCIf05zCDZAtrx3zbm5Zoti5VWjScQta3sIvXlpHyQkCjB2varsGqAsAM6xbX6bHqsYlZCwlk1uP/VKVdUU65hWydtK0mJCHJsMV/H8ph35q74Pd6y7yvcwg6oKZCuQCA+Cd9TiyAc3Nt+wXdMFlMxobEz1J0fL8o1BKpsKI1yNn3xff0/UITO4WG/FJ3ryJ1ROrErGmcxjYSgvBsYrkhIUJRMx67aSnqHC3oQ7SWeFeJrTuyyrHD99crFg1wWW/Ny7Jkko38NzNnHHArluH3t678lUA+iwYkFUmGoEtS4GEav6aW5hU2cvXiL3Sgog1Eht3LcHBLRR5Bf6n1QOINMP3Japm34G7BaoZ5TNwpgoVoJL4/vUu1ncx7WYfgP8KlUhUAWtI6NFt/vMxjZ9vhCM4Pgn6dQLn/vpc6aYRsyEZChXu0wLqM9O9zLbAQ8qEOA0e42gpKoXjDUYBnNFu0Z5xjiaRu4B0LT64hpm/n8NvjzD3dL/9wv6xCTKdt6T7PmeIUrpxi1OcprTww1m+Op0qyeOzKRfWHQl9S3dREaZ4AXqDFETvCYFD/VJ3U5pXRr93uIH89E9eoGaZQbr31j5m5aYERY2ZXF99fhxPSyd4rranhUy7m67NgGGaNgdqnH/9rR1NPpFb1xUwymj4NoSg+innBL7DfFKsWMHumXC3b+C5jvg3WudMgI0+ODGO6MoYDiERrxIidOP5q8ZN4Jfts8pGffE5/sd8zNMP36qD4t8nF/pskZsgdOVcsUzPmuB86IFlV9bD4eC/RdmJS/lHgmgQ4eTpFRNADPwqz9vkoPtQurxMYLqnrF7LElAIGXC0U6k/oyDz7SKDz27N5B7ryjSs0IVLV2Gy7ZncOKbEyj9CPNXy9vR8rAIDrFLa1QNw+FwYgPu+RoyTDJ9S55NDjpALze3Si28hXfGIoA0HSvM4+r1S8EfRrQmWs1o+qBh1pDKt9hnFpqLjq08Kz/UarsuU/dKAxkzP6FSPHWRYY3YCd6U4lJq9LL12d9FcrgYIz72opWVgWq5BNezdmM5foqsAFgDujPmGbB6YdL7kTyt0rcxMBkjlP56SnD8hLaBG7oTkf4GCzquMcMhaFf1pklIKJi90kufl9CDN0eYHjnF+AzeLf1p/Ruq0IehmliQXA1No4mXjiA2qU1BnmzqTNCyAWN32S+fAkeEfSd+AdD4sMJSSLUhNwaoTQr3qSp9Q0qW2KZGchDCBDXE4mTCyxPNDnHCSvmq+ayDviJacujoKbZNnuuZjgJ5eitj0nuD0S7jD/URAoUq8UAEzo1qq5eziSUw6z38U0v97ZaU0hohyYSgjBAv+umzJOrnY+Wu7SVW/53kYb8GpMhwkgdvQRKZcBEUuR8o2LmYWilmZpKyH08poYLj41wtsUQaVqhgItvECi6G1V1MRg9BzvvHSGxU3jglpZUgzv4dhYrUxabLiVdFRLyAtZ+nx5YSidIxtStPEnWKIR27k0BIsYLP0yO7npcBkx9v7urwM1oh8q6o9mtPT140KgBqUPMRKujN1Qiw0kQ1BM6TddIsUWMS4Jr6oH//jZqDqOM1BgFjEzXhdWWTnwHe8Y1x35EGBfYupFepa8/H/6iB8HUnbLcEg0sS1Hla0OHtaut4N6i/rJNlfBAYjK1tyDv/cwm/bEClj0JzLRWKjf1Ae/1b0LYWIDReal8V5YqrdkB766d1yx+xZ+oU0c2wAn4ij+Do6RRtrV4lTFGs/PNS9CpiYS9yt6xXt+2rFuKuWrDxwLl5krZDJKTvpO0s9aF7jjljsDfcaKJQQTlTkL0h1z/KZxm41bg+KcbsyptkUR/8Xti/fBFOUSBOUd2E0ppEA8/r2pxLlIYaIQb4dYsI3bqvONiFviW9qExQQZ2RYJ9dLDykZiujhQ2nEJQOaCc7e+NViygsPHE0NTb24LIPbnAQX1W1PCt8RtndICZAJI60dVMni+ctjifd/hwY0Llgl7d866veLh6q/YZn2f2qBr6ms+ar6mIrT0zapYhNG+hLWaXxThodnNG02y4Ifd9wFSEkMOqaeMXxCBRquJ8QoH9wSd6nYO3VDChhkPpqdATuWj5/hI5SUtcmDOKTe9FtpP+sSIII8thsMraMi34XovbHYPFdAwrSy7P46GbtrZKTG4gKr3ZtlGIMFlYEPeTPL322mNwjrj92Xtiv99blZVyVShhhNHlHvcFPjXvVWiI3iNMcdDs6Q4ZRSjkLTxVaZcFHL7S6/fj/TeKcISQMVvW/+80GI7791wFpgzGt2UfMHcCakrxgxpldcwlqSTVsMDRMkWaQQzsqaODqL9IZoMYyGJweawPyIFbCanAUfBpoJJUHrPCPVTzsG+5TupSkaxAqSmonKiCcqUA4Ra7rc7B6H67hFyaqzDcQ0HnObKpJp9Z47+70k1bqqE5DzVn9jE/pXNBplDGe2EN1ElmWGZ7ZFl5RSZeNxhCZ90+qOFe0RfYZyk0g7qi0KDnSmIttTqBNXzyktDJhs8cqPvs17y38gAjI9Q2RtR4ShU++7m/id9sSjv3xAHhawuUdS9Pgj+OO554Xezol7Wdn0kx+oTnVEZsOUDtV+8dx9M1X+b3yhEONQZQnpkLzz5trviuVmzgLKxgopFB/Hmh1d+E4KOHkV/SLfy+a1bz2FXqUzu9fX+oRKLKmJJD5Y4sp+/gJSH68oriVKGq+hvF4F/RBmkKMXwE8KTw1LUFl7dMvkMuAKoNnklEyyyVdKit0vtj00CqZhG660jA+5z41hadJqUZ+lK+ITqJjvUrjmKOzQ0q/CIIJETrpCfkjXZmqb4Ebz47DJ16umz/a0IWN/tiFyuwoxzvdGEMGKQ7o8Pd8BciB3LBnFUoHMtR0yW0jxctOzrftPZ/vh0JSHOp6ux72Vh9AZgi5TphCRvcpKlba/I0IyYzkevNboCRgYQP+Ap5rj+93nXiGWTfRk2mSpyLral3GHzhAMgl972OIpcT5/Jm3DX9Rt5xScquys2wJ2dVY8lhiPPr8zMvy0frQL7I5056M0eQjoInwws4fIZtBfEYy+ycrVnZDK6EIc1FdGItERZL7gIhphZ4dcYXtj8cRF6l2PlQ504mB2w/WVH6zE9naxlibeNF1JpvRZ5pKl2Jna35M+axy4dgC7rhji2OIE6pjCle8ZW5yezeopFZ+gelvlQrNqVR8pA6lGoPp/VixuWxbDG0MqAYPN+4+UqdXGvEF5VGcjWCJwfE31XaLZNL1XKfqzBuEAD6R6SuRb4ik9jhKDmCOvYyF2y2jxovEJKGv2qQ04poITEbD9Z/VoGI6qH+Ldfx/pHSxxYj8QfadppQBhfWROJ4HaW65WXESK7kQnLKzIcRk97zLXiBUAfDnoROqbd+VzlfnXGEogSfskcNcyn40WdRAZ9EkO3qWeT8L7eGa70tx0EDmSfkv4EUZhKMKbJwsAyedmc/tmVQyk2CVQCzgBMW5AdHgfkaHRTqiPuRpkSnVVCfi5yUcfdgKeU5eho1iFzrBJ5FWc4LtiU88uOOFewUSqski12Z7xAZDF9QH4eDOcWEIRwy8nzflI0C18Hjz/AVBfeKxfuVf56MJD1M9b5ZyKgXF2uv+2rtOC87aqaGDKkmG36eWMjUpj55xm0OrxhnFYb4io1c7Ar9GHOTCp5d9T8b8AlmDghYu9Q4BS9eu1fC5mk2qntj0gbtITw9yrm94mnFR3epFBM5VimXsIKyfkN6vaxi/VYxLzs/m8P2/iMz5YhDPSpEoE6dtGi+RYFQoGfmf4Kp51MvhxKpBWzIKUZ4oVo3bSR/xTtA8g7m2Cu9TmGyGzoRsGZVWPwenitAOr8BK1F2gZIetevGghmmjb+dsTllfsZSkAVO+a/QWVxiylobFRc/EGg1uQzlL5YM9+6L/vwXg6zBN9kGoGj7BzOCNk1aNyPkub8+YZrb16Nj9GZcHqGJWRlAqG/XekCaEDdi/tUuwHPCTvJpmceD04ErapLgvVI42e6zgSXMnb4xQ8znJCFT/H85Air3ZAMw36GLTdxZbw+csNjB7990zjLDB1/gslSZrLuBFvtO2ciWE7AqYJd4YUlhLF4iLpy5W4Sw50GjAW444Fgp6oVJnQlL0tV8APr2xbLWp9Eo40IOgvMNVPwLP/v39jsXjKT+VrFgPBaEYyxNIKtx8MAUPhCaPKzpEL58BAo4j14o00Ma4zDTGbFWPXFfbTMBZtDjBD7n6z/GJZUFz61giQOlLsQ0APQW//bMxmh8FgqEujhae7IEDDgm98plwNfmKQKAv+nZB6h9iie1nTVLTm5P4ZSw+v3VpETskl9Bq8RT65DPNdkO8pqMBj8J6Xm51FlrR0ErRv/ynI11twA390S1F5cLg+OLAOx271Of6n2wxWTJG/peXEcAVfFaXXlsmvARiKku8WQu3W/38Uulrk1fg3setfivWSWv2nJvb6NLQyqX1aN5B4vMtm3Sx4oi+QCmHpKr4+n92EdLsHfZJa4Ldm49Lqk6CkD6kncpzbtAjIRTVUXcC/P5ujAwgZPyCyhiwkRJnc1ZBJmbF8JianRsBqhnzXpUBlsOObVOdyjLn3rFDaigXy90uf3vyrSJP1LBqN6DjEKFm3qQXpgmEIqfjLN1upGeb3/PrJV6ylEFwbsPv03ZZvlHP6RLo2fOotcZBh/E+EVPvXv5bzjYVWfDbV3wf6qnr5ZX0muxzBkYOnVp2m0mDA5cgkhI8pY8vXhQvMRBPQpqe3OPJmr1HySivFsIWnHbpSKfTYY9BJYLlEP7cQWwboEHAeXdMpmTx1IOUnJAO59nOml+xyOCSwelJo2W/nCTPuEEGkBHLjpogzvEBe7DZ8j4CjYynzKdd8UEVuXCkKvQhDC6HGQhd56b1uxmxh+Aq/w07/nYu1Y60vEk0Mbi2s0Jo5PpcOcG3ZmRXGJf+1csDOpm4wCi+iF84wBewgxdIegpjPTRopBHEPYH1MSRHiBliqdxf9gipweLAX6yLOk/N7H/gqXarYkCdZXxEjpoZauMfawkM7Q/wSjTKV/vi0en76dmnTHOQzAUjGfBEdm3DtJRZd9XNP27syr6nu2mefGeB+q9sHnNOIMkn8+ZBd5aQdVZT/HvT52vWseAb7488OnqKWAXinkPMoOpx151M5Dwh4n5aMVSqD8+cwTnrSlcuBO+tFrxdDhpCjOY4HRq3Bipo8A88g5OJPBxTCX4Ms9FSH21e/YFA14rMyjYfBMSz3rCdSYp1Ni/U4JT4mU5wGxE0/4djSDcJVd69oE4XKftnVrZQuxz1xKObEy3VSf0/4VN+GtRu9PClRTv63n1vWX4R52q3ibpWD1gSnCxUnMGcovNWSM3+syP8G5yZFHgH8sVuthC1LvODHAa1r1w1gzLAWMMQlYzXo0CRruV6bNDGlcp6KZkgbmOZDX1DWXkrz0r1sTmjTSM13SBuBW4EaNJFyvoV5LLW/yNcUDzhhwysPeGF5df01d+svZEAgHYA8Ogf2b0U7Twj3zx8IqyFfuk+q8TA4trDvU5z/fDNnZazo5r526djNB9+vNMRuxziw0qf7cZuJVMHR5+ek9t5JprtGyXisj7a0LNadiSdFxx5hyMW1SStaM64Aj5w9+m1wGu8Mx5eZ4YX6tXpnc6II3+8SQY20Ui9W8niZVOpr4ybqsaaHVGW9Qzxm6UJwSjtgOcWVb6RsO3i6ymooRxQbpZv39tLrxc42g4Vn8hb6x1i3ukKrvtMUvidfbdR15kWYyV1O5PcPXZ3UnMI5fJS8NhsFLE60UNzIga7p36e4W3b+hKghoKnk6JfRtSn7W2dtJgD+pJPhKOxuOLv+fLBT5FwIOHtDzSrdfQrIeiw1FAOmemg6VLbIGiZY86LzBOGzget0EKnLBmMEZip7FK9xIPno1ek3h+EQhg+aDtm//h/VR8Zaz5H2ls6UThDjbVVBw6ffW3Nl71KdgGDk+/D1pvVIc6yfpAgfqt2IYSIjiwJAlvqWZWxR/DkZQUfO0Tjx7fbWp7dssuOrIwo3KQALWFLOBCEljuas4Sw15z2kEQgwquReMhCByUT8vADZMeN1VzAt6X73/ZByCwoVx5rxFjuZkfpXOoxeSCBJtTBCbDlmKHAEb35Fo1yDcQDSk5TlcgrFG12VRpLkHOlZ+fCRn/T49V+TRF0MPlTh2yuJaAl0K93cs1uqqRATX0KsF7XdQOU9FMx8gr7YrImpvgUCheB5XJR1viAxxKCQpaAPpG8SyM1eAbTsNmWsDXz0o9b1h+iz0Pndozebu4NtJLqSXpXCVSsfLlbAaCdHvQ/hb7BEGKf63aL27oNfROm8x35ul6mLX3JWheWr1oPh/KwLgJhOlMPUEDTDMzSp9XpJksZuB4ricLei7rRIn5YE/NWaiswBb5oknS4hicl8YYYRzryUqOdC/7z3GTLXpmFP9eSolf8/Rzt5KNtJQWQK8SoiAbu4e4/ScgM1wzUaNnMNQ0RV4wFAwZ4vvkFNDzVAwpJqWIPaA/MF2cGJOfxA11Ssuxd/2gHXF65fJ1y1sOi10yNWjdnZjjnf8KEdd8ApKjNpMzD2WayEQXzmXXKQ5Ym9FlJb1oIsSJt9Fv2YauH0FlsSO0IWOu7iMPJ/Z0mo5ka31AtBJh9c1gtUxm2xo3t1qhMGnopFozQqeZgiSufSQ3pgrGrUqjwzCsmRZ4qtSOaCu1eDSgR2+DTJ3kSjU9IkiII0G0vFvR0bwL7nOFWBHzs8LT6eQic/CCMCJXuxvvwTknfgrDYIj29BMK5Q/PoMO7JMlG4mfMQ/65QkdmKvVVdmJYl8d6kHjawEtS0JsTwaPFhwNQcXXR4QBFtfZq7hZTyAl0VJ641n3FdiK8YjUJRhRVErBbY8vpSW8Cw5DXTo6rVtbmDM3GHhGWL/EQmL4yVLnmqJloHiCH9lgCZ2spd6WdTbg/G8lS81eFiE3AdnUvL8nOxCVE1cm886d2z5rJL7xXOBfhXiU535UD1FTXOt9IJAGFOrz3q7a7QBcN0mXqjabPSLUzao7SLxzzQ3N5BBtY9E5A6F/JOeJ8k1azGBsbBmHX3gX009gjdyh2FEi4isGWUYmq/ppVDOKRM9TrYBIusyuL1uJnvliLE41KvUnj9cVSGu6Y+LhOShU0oIZzNqlLz1drq9WtJ0pNOBHHcDBUZIHKWkvQu2Kj08LAVuKoqCUTB+bbFSubHE8+P+LqHhU1Efi+bofZdd8IImHxlzSay2TwOJmYr/vg1ttPsxY6QK2cUYrisuDe9flpa6aZ1TDUghwOD3SrGayV0EtJznsqVdhFFrMhyJVUZNqnu/Dacu5QExvHCzFWycNKt5DhsDafNS4OhLlgZofPhh0ORCnb31pkhnfZH2ViomqngfDk3HZYuwW4eKaQuzAskCW9lIk+PGnnNa4MgKye2sy+Bth5Eyn2Y0CHD3wtChNaro+GGoZpaiOyv5qbJLbMO1FfBeD7EGb4VXFQF4VBxnnGV1OFZwDKoa7w7L//On/9Nq4eFY8IJABXL/JWxphpALlAImWxSgoAg837PbDY9dbowRSrVQjhJZUM09BEL2FR+P3kwPwmzE3ReioFgvcAZtTcjzFZs2UHJSk6Mcphkd6ZCr5HIcqgC6GXPa4Aqesw89Uxz9DZfpR7PJkygyZQzn+nGFe9UDOfyqfNF4MxitwhtdniTtmpFTc2JmTNNGNe7IOzYE9kwB52RtLgi79orjTDW5DZ5TnJIqM3sbis0VBgUGXb5JY7oVpXPDmp5XByCkb2voab6P4uFhT8C7FmtsJVQyPRlddFGilUPX+V+n+ANkBMUhuMdowRyKwSxfaNsDVSgdTuGpOw0N2qr8kDOM3NDaCSUXNLoaxxW0NPdO7C7gFI4vcdYhiHy5lLmxuJD62giIjMqQOxH5cefdO8+eiMemWEBA8NQ83eQD+SCHuzLgo7LoIvZmzskylMbYFIwEIzAcy99HjGicmpxKzHFHyN+CRurnuNxaaMqx6/iNmvXjrftA21yI9Yq9T3Yip/33ksWdy3c7IGe+PI0WYExvJ9c/lBmMd6SGu8mKYF/pMxVOATbR5+xtU9EPvTKfOM7TmG9K0faNj7RxdZdua6eui6PekC3iqcWyGt3EGe5j/do2IYobTVDKKhnMZnSgEOmx1rTBo2KKbY4mYB+RtNvMhRJW4StmcRz8tPcGwZbrgTCjL+D6d5oxRiiZo29zSKfQ/yxmLwBPZi4v6LgZGpCMGcUqSSH96k7eBtSoifW31yPc40wPMNsgRBozhjEagoHnrFGA8uxx1turvhD+04CaMdCQGjZ6icqM9PZrL+N0vjxFN7feMPCHySBixzE/k0gwDf7hpMwZnkWoBwF16bK8pNYxmME9DrFDMG1ZVELOxH1PqMzOqDTB0uv/9si0Y/5PfxIk1H0BbpxVOacW9gDfuwaxVnRYlTl6JDYgDqDuXSAokO8ldVhABFE5RQdKb1J4nx2I7VDmS811kQTLZlZZ6jdvLDKKVq/yvnk4j2rXW6cC1j8cJ140GxQXkK1EYNUV80o8Zix7dY7gJMoKBsCA9hXFD9nexFfhUNHwcjYNhR20syWFFJehOjNJIcRPibYc15Zz5AqnBLYgnqo78xogpUJYMsClJ4ZMBWfGSuoWWio9OqVU3LHKfcvBEU6TD3xWTr225Cw6UVNB8c2OqwIA7Q6a+t/mvH1EKysRXxsk8iOTZ6b0PM66iEtEt9tDBAPzCWrAY4c0tCHRFXyq1UuK7lRWVaEnrNlpoFW08Q3zpt1nUR/chEBfQNOITrI8/imqT+CMvM+0hhtK6aokFYHxdOXeFRDOoGeH0/qfVCAnxv/XLz3ZS1+qeivmj6QmjR+3sKYPAMRv9H+YzvZ+ujz2VW59RyMTJaZswXzBmdwYfL8dSxo7tgxp1B0kJiKMfPaTWty3zszKcCc72NXo+hhErdqfA03QPD/w0kYChY+rX321xwuVFltMhDKwG/b4N9mDi5be+8lpEMlQsguMMFUPwJRtiHK+COc2fvo9hujDwtxhvv9KHE3rouXBsqhqVzezXbnSCJRRQg++FNw0pApZIaiBJsa/oIG5PtnyPFCNSfIo9ua1/gp2lt+Y5ipU8AXJTf2RbmbykJqlGUUo45aqA3kHtH++PNVDlbJAwX29qRziiS1OtvUQw4ld30U5+phiaaVP/Zq9GOs0KT0bernuZcmtau2dv27jESU3l4ipL6yaBpqzRfwWluAJhVizirM9O6Ao87LEahalzvTjnml95d+SCjmf0G7HMSGPY3KMiZUoyeOZ94XSMYssRKNnkx3mzxJjPuH7NCW/x0HsUxFLsnDYBl0xtYGKYpIAJoMIzCndZaD3FtRj9AwzhDNe0bsI/BwQ3GizTyr1TGCdXKCy+NaIB+5/E5vfp+1Atqey0P8Ak7ehDSNvs0NwAItMjNWrnKEIBVg7VYs73s8nuf2rXF4uZAbXAoSuljxhpe63JM7roasaBHvCA11M2/rw+vvLgBuLUjdGSbjz245MQBTwuruVCg27RyNT8kyCtDzqJeXC5z1WSLGUUxmd2YN9tJ6/Iasx44EILMV6qJbkfJq2VmcKO/w40/KM8VqOHuZLTQIf8jGWgn6bwgady20kUobrKVMR5/vX2CH8yBxBXtjCmfPede3G74VSjUB3afEelgGPcDQlLia1r0M1Fh9eMQUyQm1zUht6iHGBBfhA0wh3fF2wRVDrMDe0+0nNqknX3VT1GrKm3sZ83xTirO5NNmKXt1SCvF9hpueC718ZnJvfF8o0n29mep33pAy62WtTkR+aMcBEsaDNGqbXfXB6SSg6eDcpc0AaUkawDlnnbPOm3/HVPjpNVngtEy94+cVBDJ9c8ceeBVGj6gcKE2RZYKRLAzxGshUKstkT4aO8i28lAH2rPazurAlVOuVkcJOfXKMMREeoU468NNBQti1Iom7il+PAxKMgRmvgJ24aV+5kSOm6oFyATQE/RAhp1TXP2jWfDhgGlXptbU+Qf11TTOCKYfTmiSVBSwwLZuCxUhEH9NxVCWBHi+OTeuecoa+L6Ma+AZhfFwi9sKOOUsQG0BT9ZApCeg6o4m0XhqXu34iYHlNxowbrnkXKrN7mPzilOALDqGnJSX4hLsSHKT4INypfPH9qanWiFAqnmJ3/E968Jk5ZSa7hRbm4OUL1W0tpfYlsHDeVnANkwLsWBd3PLIe48S/qhzNzmDgFF1Py8fHc5Jp769j2WlTgoponm/1y0YsyBI/ywxaIy1y6fVjKqJC5HqQVjkLs+SrwIFDFUEQ1dzTAbhd5+rEtvz+jgpTGvFpE/7FHohc3iRLx8F6CcVXffFFDZmRcs0VPqmOyJwdVd0x0NECEoTHBvYqrpV3+j+RAkibPFt+7ultMeBxwZY0NQ47GJafHRAg6Y+RiOw2pPUqVRjeiP9lUuAJfH5ACz7iFZ1cIr4zMt9ZSdrdb7kjw/D3JBtVPk95Y4J/iMef6MFf/qMmbf3JhC16y6BnOr0T7rw66NlaD4zpR8jIOHFErzAhJltsxcHmcHA9GoAEAjq76dHMQ6XrJfC5zKlwLLlmndHniu1CKDCQ4PXqqhMn8Fi37/tMV9fhJ3OXliNa3ZV9gBDYZ9M9MYwGE/j5cIK/tpIK1PFdhX6rI9e+MS2rjVuWh5/2vFVrI3WvzFuOVNywdB4JC137UEqxYIaZW7Q1MI/ZrhkLuAN1UUBaEzFopW4Mc3MTK2uSmTa4a8rinCM2ZbWCQQjgGgyhkN0bnrXlVtHeznx/HTGFQQtArTVtVygtTg6+GpvDEQgl2PM4eU0GOe8NuyTPROjOGNh96apt3l+9Egxu6JEY8yl0Wq97Y2GDmk16/Ki0SH/OwA34vSHFxsdFHUkHWHuAqI9V0JL8yZoNW0YASL+w26rbf2Ldm5GHq8XKyIyPoDeLpdgGT32Mf1XqKOFlj/DBbCfQx5ZFC/ifuclNbJa4nGorT/zaiFNoj1AZWBAzik56ysnfp3dGj6XEfJfcftQ+jEeXXwyAPD7XvVI/uXQ7rdKW+ZC3lzKQMvVCQDCn3QRKfQADXkXNFK66y/RLZiPg9aFBKLA/9dDIBa1mLsRgk0pQyqCCfrrL5Tur0eKPM/JFAg5wqYtpHl0wc2zAul8hDfIQI8UEFaDaySgOcSmD9hVJ1d9Ju6Q6Jlu8xwvorK/UeYQDjZ/vkzzzxbvJxILXsLqcnInl7WTswak5kRwvmg8BKKkxo8YQvTp9c1bIwtH3aKLSKTAYDNqSQPv3YZVthoOxfNs3EQRJn9VKa0uZ19E2nHl5FnbrUzl3thPnl662rhNbKBRRWfrOuiLwKx0MzsCdqIoQNhJcFjUZh5KRjWzRVPeIdoiTc4un9yzjbcFu1/bdt7Dd7q4vp9CJlYb8kFHY0KZH2/AF7LLGUYLuL68uh4kKdbw3k83zMwQO3MFRiV4cm7uCNsz0JZmFmYh/+uk0ZFY7CMX+ZkAEpoiT3tLGOVr9ILS8n1dowYK0+PF6t+QWBICSrvkjYRTPEKrQIEsmUVX893EvbQfSMX1h2W7U1XXwcbP6rV1pWhPtmoX6HfKREigcgRvf3EeUOQ0pOMQhVo+lXmhRkcHqsDVF5J6bf0xZ0QTgDEEznQVb/7TUWuhUzTH+yPme9yKYzu7NWPwyoTXA8aNlcxuXLiGHytrfxS5tjcdj2YpmWed2a/uoHeTyBrIMwnwNE/39vsEeOK4CFmdRXoFimwIBhyRJ1QZtdxBimAwCq1xkfF+zZuEOgCsHZRBFP+0gvHBHJg29HoM0/A3p8RrucfFXzylTzr26zUFmUezCi1kIHF/3se+SjhV1D2lhHdVp4hAY9O6AeBFBmwfWByV2vr23g3UJBB22YqKoJG6tA+2QHax2IXY4c7CHdzxVdUZCXUlEGJsxOuhU8NgLEvk//U0+AkflbRxxTFHQnMRnXAJouv81utGIYGIkHdCIz7eSVJMV+YWLsFU76A23y6d7u2L+zvd8Tb3kxYaA35U9kNZbbd4NeGHR6rCnYnx9ufaxo8LDSAqWsH8GRkfxqtND7VNQMK4Fh/iTLXV6aMf/v0XH3EecB99f39Mf6uWhUyNPQlIMHhG30ZzHnXw32HGWgkhkyITbSg9V1FERN7ohQW8A9tFv8OuNRZps1es95IGw1pisq42NF9CCXKBY2t5i/VS06sB5h+tkYSf5VGkq3mb6rO/AZLxqDNNSJ7KCszpyYXzOu+4yhTwy4k9A2a47CwiTzLGgRyQb06tQNY2AEpoVVNuIVygbv3e9CcZjv6ErSAfGJNuBqhHG6Kphor4JZrJmTEq0lWunte3KAXpRHjr1QwP9vym8HiMN2HKuJjFJw5+ziwZtrBhl2hk6IYac3RFXsDvn/oyBipd2mBa3Rez4l1x+vc8w8jEIYT5gDHSOyO7ufnLrGfrM3iKDAujCdFzJUshJgoCY/ryuLLieqmdWqDz2xH1fg/2t2mWzg0BViENG0bf7NdzG7qzH6y6xrHFv4uwvKqloEdyetwT2WgvcY6/U8CQIbbrEW1bYojYszxUQAnb527OsTSZMqDLxCEXoQ4/GeGceaLqw0EAHYplDC9pF3xNjXbAiW1VY6WKNFtl3Ml6/2qAL6GzPLYoMFWgR1v+fhnX6vlJWxrGt7VWiqpvWUKfzyssfud13LNxcwx4sJVz8ejK7jgv77Qo8CHm2pJgf4UWOFL+GybX55euGZeqDc6vYeDV/dzBD9phAvSE9xQqYGNXv/dEFxddPxtdHiDeFULEekiLa2svfD9qjqWOO9SA9UgIxb7ZORqZK5JWaiDjUg5tvC8EbLyX558cyChLgvliXcO/X9MdECYBpMWjyHBGIleEtTyczt3UjcBXJJroTRAVhWDPDppn+RJHuv5Cd7dccCbbOJO7EzoI4A+XyA/sYLoOxyDDVvI7oglQ9wQbyhiDZIy5KLJc75IKKwRqsllIS60gv5a53PuQ3UBnZIYCEGhiCCTLNAzqL7aZlmigdoHFfCnKrg7QDF/OP2YUH2NOMJa2mh1uutZgsqjqXIKqlURm7E998QOG4iwHd+576/UTHoa4UyzwN3jWoG+8Rt1lpuyqiRckEfr/vB3W0hrKHL+T+rcWwVtbc3dU4Rx5hsHoSJxOzTfnAyBAJStVRtm8qivv4LWBjyPe14bZ4+BYfPGiBNdT7m2d5M6c4CtiqNovfmdLTuAEQmZmdcFEPnT8cFSeDp/cuZw4D6c+n9knCFj4T3ukaI5cuIm09GzHti1B5zCr5mGukDRsjxDcAcd4OYjpLFmtaHJf47VQ4YgJbhdDyl6BAKrCqk3nHbUTnMDS/1mChN/NSqmznLzYns7tlrm6Nwp+xSz+X+Hm3FnPd40zDpiCpIGoEq30DT7JITtr25lIy/po7lqbrEBZuhuNL8vz/k2hh8d/bYxjCbJaYBASN7maVeg/wjdrVPJm5oW3ODnsoOw9pT4XQoTVp7YdfFuKGIEnphrIjCMzO8vIvwAAnHZlQ6qU+FMTjuqBgaiD+U/4RJCtrvgcUsQtW1+xeilQk4nwOuJ9dd0mtSW+2YX27tF2RrTX7Wye8GZfUBfUzAOOj/NbZYdce/LWClXdTUFpyHMH673BhCZVfFpdwKifOnDk96rclbzRJfBT7lzIYqdSyZxk21hi3j/iu9uZimdops2rzxlvqYd2PYOfRMfAM2zzqICyGF6nsh9belAWjnHce4hkGcPY0p1xFoIN+RJOUflg6k86nPpLeCuSWDkBdq87uv+ANQHhOOVqpZZNLvfsSlvdU0dP79iVGgbqZ06SQnz7Hdd0elReNH8cMm17OUHhbLlNCWBsOi4EtSgBIaCXVHo+59K1zhsTN6xScR1A/9UDl6ToSOfutFHR3dGSriRUnpYloGzyB74ozqPKVMrA9YdVV1cCTzVvGLJWpfHGPkCy0DxTsBNK0MYxWXDFzTKO3ZwUZlHZj20UEqHe3O6tg2AgME72UFOT9aPZ/errTwDVKip8OLh+9O2ZHh56oN27fLEDBqBTGiLBdfmkxbeskBq5iY38ZoCoGp7Zlirkxk7IDcKxnh2bf4WG37FBgkYtCVN7AR8h8lOsvwLurXX9mvczxW3kO8usWT6SBOH3rwk1qZBD2oJHWJIHnDKVljh9lnmNdMW7DY9m/3rqbSU1X/qmgUDLcScbWQboRIJiSL9ruDLFOdi65Qc6pn54Utr2YOQpqm3Va6SNgQIytMC+DsB9MubUqJe2wMKruIVQ0/A6XkC6S6benIZmuoSyWm2fKolo7iWLcw0aQG9qAY8hTXWzd5DhR0IglH12+KwiQSzFBeKhmQ6OfdtZYBlU7TA2pcdGCdXqoadOOko8T8y5qwGwHZsxdgGhhEqgXx0tm52V1/T93rn97CbPpbIBLDkcmwHL9Sb3r9nd1dXJ8VTNKQMrFfGXrmWk/Q3yToZXDyb07bxCInVMF8PMP/4/o4sKPM5rp5uahwxfdOVDsI9Npyzv+fdtLf87DwSeszdGmVPElV8QFF8F8rGxC1BBUqYoIAON9Rkb0pvmNJU1QunkYJHwB1Qf2F0kIF4RTcZzUv8txKsMmNNsTOyk/YQCAm4OdHUjYOh2Iw/Cp39e8vOtB7rl8+/hyLhDaONbIf2hqHI31CHSewz0B5iZYEp8KXdnX6nH9JjrRfGTWKCC0gtYbquHDbNICzwf6QjHB45+k3x4RCUxORGbZ7dozhUrSWQ4/pyM4WSNLUaxi6Kr6ThwdfARDPrc7CZZJlcCf2dBsFGfMMq4kCtWwbMWQnAikrP9epFgicqaRSvyD6tRALfEsiMamc7qGL8IAA/RwBLrADGtXRjBCNhPo/XjNyi15UD/RxZqnY0WUzRccpkoI1Y9m7q4XDrU+kBhcRDwFd1dr5UimjTQ5YBNfOWZm7fQqvNSp3Ke68cKr9coPSRfFME8iJU7murKo5Y7Wc8Hqdm0qXb02FI64e5BudV1fCoRsBusMlhaFAsGkZr3hP+o+0c4/chRVTX/CYN0eQI2FrYCatrV9jLs5U+M2qw/L27IHdAMDUyeyZBqSM15S5LuPQoUouzvL1Q/wE+pDGFdjaqmnsaACkryWJFEvMrf40Ofu9ts8x9J/vBirnWDJJa6N3OualPCrhL8atPPtuq0rUgGAk0KzX7Lv7DLtbH3sQ89Xk6+rImJZO2s3J/RKFafY5fHN7tTsSOEGMtocrp2JzuqqxsoVmS4CY/nZYZUTsnNeLeBEuntE/xTcYyu3pC0UQDaP1o77Re1PHmjLB6wDGMPBnMC+V0+dEa7xq4LhjnR1t1pF/iKfLsQ2xxGeySQcJNb1veHgeRWiXRimiLuKl23l2oQzTqYfGAtw5u8+nyksWWY4fyQBFZ2DGKY7YVa/7/42B+PsYJkv7Cnqxfig6L/p0Gom2pRlQAllbkCSXbcWJxrw9yTYPW9DF6nlBd94K/xdyOknqY++bRKnENbYKf9uCr+v990BZuew1LqGyp1n3HMe/V1SXa0JP8QQPjx/w6Zt61hZFfu0PTMWiFxFXylu2Xa73Q6iN20DR+RYWCYQzpmUFOddl+fXxzgQA1ADpAjyqpg0vxQjWUU1izYkKZvxFlrhcqTBlbwgHaI2ciVZJxoJ3513RpGkyskPPebqzs2vlPL2d/nGOn03hq+iNxTDb+iLVTxO3fVxV1qV1SLC+aYIe918c7fF5EzaaOIKVqo70Pa3njEMFwI2IQWKydtrV3121YQC+h0n3C9TaJaxr2leQJfLE/WkH7k8qqUnsr1V8eiPNYewHFoZpvy3ok553HCWLSZUrFNPkrjU/3AS+W08BReYDGVQzDg4eZPYwCmNSb4j31wzegAzO9YouZuikHz1VGz+g0qPKBcPjTvYtM0BFj+Ox/rGdtLk0dNXkLfBGAhlSz1kLaEcox4zlKzcSUPpVQ2u8sPp44B+H5aRzH3om5OHoCUcDADbHD/Cs1dFXN/bydIklSH3BoZ41zuAiGrNvGdSGlcJKeoHPsxQIvSFqnaN6pO9VObYkzGVRoZyaPxu5f3RFIvnDIybqJbU+MmhYAywHLXNOfxjzbh7N8IC03TenmCicLAO85xOSBNhYpGT61FVhjFaCbh9TWs/AATaR+g3pbyaxxjzIG2SvvepbXKi44AR/Ym3FqGsvHG7KtrxpctfTgsv01z4d8FEpqT8AL1I/noqEANcb6nEJUYnKlKZdXYbU2Q4JcFN3jg24EnMsBBaOSxZANTClPYWO2YF8QjkSgtkEpiwRkYI3CF/S1PG9+a0nz1iNIRRb6AJ9zjNDBAloXYadDKIBhQJSzo8lz7ngG8xV7CMeeO3lKBKj0njPi+4wdHWTc0/hgHAm+yThEPMdlUeIZWDBeGvhVXF9b2bxbfF+2i3hOz81i5uf5/m3vCilVVXDDFnECOTAi4SN0lV8jXy0n06QCH187BObk4pOkkRffoWR41D1e4XDrPpokH5gHhLFtT4qjHitwWz/EfxrwNSHaYktnLKJXmmC/WfwvSXBpKMUt4lw3QnFT1YR/svW29p+M/MKHNQNVwUSIKnjphRoFRkTe005ye5RC4mopIet+6Jmini7o9fXPqLKI7LskaKPCnD/V5kap/OsSIeDF9cx0FZnuax8MfG2xTksJgrDw50pgoJAEpyNtYTTWbKW7u3xzYn1TltVqDVzaYlZEpv/3RGozuYJAlbk/S8los7dF1cMhfvBubGrXD45UxMvP90udKq03isSWr7PqYH6/I82GBi2PALgLuOU5GhsCmtvhlFTdTxt9f0C9mvGE0K7tVC46vRaTRrej90EDbnJnwzYsRlcmewd6/rIH+m1uklCPLo2sWrysJ/PYbwXBnJwucXCq8oRp6qoC/37GTXaqYAc5Sn6XNa3vnoAAIvY+L/xUqpHC0mPUgSXWDxWr3UzmzHIcmjzuDIX7OKOZbv1L9rEzt8YUip+1FbKCoDJCzxtAToEgrIbE9Zg1VZnFfdIfe1NdMnB9rSrUDUvsL/vcq+P46Wx+VUG+Jm8b3PeH9y3ssy8Dnw/VynsZlmqxKtnefBjC87epQGZ3twjgMeB9vPui1Chbg+nLTBzCaFxOSH/NX0Eh9iI472zPQxwk0u28ZDEFJ8TbVZBBHot7MhYnDXihieqn4lrnVXZPfxD6uN1s2oYbKxRPK+5pPuQzfrouO0HEZcYJZsdl3youilvDPO5n6zwJMA3t4FQ2S03/o1StOtnb4JxfIJu+e4kaflH3bTkXcGe59p4nzqic5TJemCJsp9kWKx3WM2NHpJQnLQjBrhe4nDsFAJt6zRkR+BYWFmfzkfBBBFjrLrZmZxjhAop0WQ3dqZ+WGE6xl/pelKEE3Pk4yti9n/uvHdsp6h6VhBUQ7Xz9X0BFYmUwLY6rOJymYOycHHyxX5iTiHKD+qQHf/gwv4EqIAzr3VKGC0wYCTQsQNuf3K8orcYnmT47vFlOJ95EzfIMvTaXQNhOC9VvB5JNGSbbA4/VsCrD8qoTK0iQeKuFl3J9Yhfr2btBX/f4A0UyfYHNSz3ta+6QAe6O97Ne6ORcuwFHnVYuiyidSHKSAJn0UrLwIEwOk70tYSafIEaX5KT/1aT3KXNFbl5UyzSEAFBMD/CCPzM9imej/VxXQdY9BHTLp0Z8zoTOI0wjPDbVVf9yiE0si5t5UUFOXgcqvvkxYpxD+TT6Pkn4HceY9WrwbbypLzoWm2QR3cl3If+XqFsaANChpAIxtWnchMa3wYICXNl6SIUPgdffF3+EoVfp/HfpfBHcPiHIPPNLmZ/i7B6HGpZUycV3gnorIVivYZsaDTcDX+BIuJk8vt3VUkIuoyi93JWpE1j03JoB10PTzh2F+YhTmvYVjZ1yK7URrTV34Keqgdbi1G9Lo5urqD6YnRByZwsVHMI68Q12/gF4oxChR0QBPcZRHVYQ3YRKD8ZwfbkEtDHWbKBLIWJ0pTuhfIoXamdfdjPRrUIY1+ZH26Bws9IZJlQXzhHLtLNIxB5J5eyvQRSgQOPiV6lDzHZbeDkciay1oJd7pn9vz4zwPnohHus193QNfeVpY6oUjHYzAIJUGqNLVOXbY8JppoREG2uo3vK+pDI55RAa/Uf7747fqpupRxhYw32G94S6CtG5+rVInikmv4ArQ63JXH/DOvsqcqJZU6JLUN/3GGj37YTb6bdbi0Fj+NswEf9uMlueqfasbe2G7oaKuVuHW7k/YgrxWXsTILL3N/sd64g7fuxFimqTj8/akjv7gbDQX2TjBMcTb27FFG5grYO1IVGqnRJbWl+NoF6Aek3UwMcVuFrlUN4DCjEgVPYKSbZNC4oVcVWxS0h7+QKLpNiqT9RsjnsgYsKP9+FgvE9QYM34AgnVQcUOfXa+3yIauN/1QL1v+bc3iNcGKs5QAlNWU22E0WI+t0BapQZ0D/1vxgihHfVE5Xbni1mVV6MvTwkGF0V9IEAJ6Ylwx9ibUEiw0FOK45Lov1jrEqEcCg4+zYKL/OaFxuEwpBfgTXY+jzfy9NV9ArmK82AxABvg1oCe3BEcpEzAl6M+TZVjECFLG2xLFur3XvdV56OJlBSIKs+IyYnTST3otnvKhDYsutjMFx+DT4LUciFPRdLqDmpn8BqSxynAsQ+PM+0rXXoY4GPWcTaeEC0PUBdztcHhC9GGY9hRaYuRrbRvBpWIxieHq0zFJ4GXHgCEAEVSYWJwBYtKDN0Nt10brwB0jQsYTpZ/FDgI2VxOegjA5XWBmYqJaNAXuukGdX31lruJT6x6xzAx13suYiyGwlQwGMJFD2n7virZ4GC08lc5T4Z3eesZ0gonXL+myfXt2FBO+i5GPtsdlJzK4uXAClU8zdEev16HGhiQnbGVyhQ9V5Jq5DCKp0AfaWci2sO/6JAuK/uxqL+7UdadrCogXVgY+ZB4AkPYybjT5srsQWaLrmcK99aq+Cx+Qgp7qOOON+I4ZdYC3s8hHUQqo15R8DoKKIl96ATC0y+UNGHb7QIvzRIEZeYj9RChDj8M7mEHS9MB9pRM49BkAi1njDTDY6cIEWMrGReeiq6P6kmSnfj0zJVSRQGzzL0Yimb8QPYIzCkNZLemCGKEZG8FWfSmgLxFIXwNSn+3Hq8go5Qk+INr6Fsdi9g9OObotKHA5ywQ3nYeEebFSQ9i5hO6fJMuLAyFtIc4EGBHIiE4NHn2TYpQA8I+H7RDwl9FxhpJAgmU8nXyM8pq/d+KWBkPJFA0ltn7BsYx2z/Abv7119YbmBNvCsQ+hoBsSPVIlF18Y4T+d33bt3cIQP0u0MI+2/vw8YWXKCNX58JxeVjM5HyfaaTOfjXOJKfoWzmknkfqPwoKXfHd8BeUZh8nauh4Phe69WYMTJHo57uoxT6ty0JcsUWEpzgUI5mgzO4voUUMdl50X+urGkO1eSqb5+Tj/gBsawEuGxqop8az+e+ZGSpNRSxXxBgjZKJ5o1c6KaCJmfNUmt2e/ilXFCsu636jfXU1uoAnuOnLNHzXWEXu3qbDo5JD+FZ3AreMF0+9ymVdOHOweRp3vwTNTxdItpISglbehh/HkcwZsoALGQKs1B1TJOuNC/6386m5L7tVjNYUN16OglnTkNfd7P/PWJvTND1OXgn19RuyIG67cr0/Z3a44VVVeAmgO2DywCBdFphadzFqManWDg3im1wbCtT9aabrv5tZjaNB8Axgu2yhuPJodEl6ouDf9r1FbIm4AxiIYHc2eKcdcXmaOKObu0uWx9oXfVKGB7wz4N4hwWPC1MoUD7xBtEsTrUjUVstDBcIgQdqJFmuismaXDyHbGrsDsPwq7fvW89rBAwAFFl+X4c43aFY8QdC9Uiwn/w8jTM/AEJOsbase3LTmKH12U1qMuzN0jd7URhhUhoz3wTDKstmiU7ybwvj06TX9C01pBZ7o2mjVEx70QdaRs3DFC/tVnBGuWLcr/UI/r/mR003koQGYlX67oKPcgLOdYmr02RMvhlsdqcNimkrRts9KDPcH5kCq3FaTTBHSwM7DKosPNfLpemIKG6oi7Mm1dNCj/bvIUe48mWVIsmFrVB/kTMW2SS6swO1WKjRSfYgPO1ZXmQeC0u+GkmbuCuCL78gK3Ac4Y59nnZonoKOMt5bp7i9atiiuUolSDA0q4+uA7d33HKRuokxTfUxkg8nDP6cpgqRi2P4RXCDEPxqCZ9M9W3M5ng+nnDMZOmWhySvtBDVMPSC7bcxIWU3qk2S8Cnm8nSL33RfMJ+RuiMRDtGJx6l3170dHfegAOke0cwT1z3i13wt7yo34PTCcRvcXsAXFjNb1fpeljcQbSjmWj9mlMSZLXe8BMTerF98kF9o6uc25/DqyqoMA8MDPkR7w/1mQOLcqX969DIn/hFWHlAQ5g13SSESFsPcvMfyPG8FFaX272I90QQUv8HyO0d206i2vl9tXFi/y1hMhlUZy/sMAWhPE9utNSk0RoqZqfkHFvwsPVW8eKY3CdrhPscjFQ1Rx6sPk+hJS5BQR5LB8hYRoErgTuZUy+0oAr/KDW7uYYN/NsRIiVjC2LJ81Au29N5WKjSMZxv0oSp7v05FLv9mIfeAocPkMRydWRVSdWo29hCLeE0Q/aBgMOFOs+N3Ywsg+TEetMGiLpNuVLNHPuyjUDxvB9f6SlVB7IGKmTtjvDqUXjMn7Uskkiquvr6LIaudK+zk7YPOCwxf1bx6S29ONO8p+WdtUFWMK8tXrcQ7lG6Nk3aECYR0XrMThokSxReBZyXoD9f/SJ31qna9Irp4AglFgT0hSivOTKUP86J4e3RATWUftJfsTlsObd7SHlqoGKf1Whb1wNa7ZJSTLAvw8LVQlsTIDRjfs+LvyJUp/l97iuHFBlBJ/sToeAPaWxfRHvwkkDP0YNAqfa+8rAVtX3LteR/437Be2Dh1sOAwH+y2p3H8lwH8MhikSwQrnuhrXLb+93YJIsI6aYZpkUW0cOmsijblV16mVEInsOomkiYI4ZExN+yK6oKgfHqnKmigS6Y7TQYY5DifbY9E7BJkp4Bm3rctqiYgibl7fOCpxT4INNJUBp+BYO0lGaGZC1H5ybdC8RxdSx14TrMJwV/k58E91IZ8MC/Ds8jSZHp0dgyMZetyvc+l13fw+Kj9sx0eFw/P7ROZR5t+b5KY6S9wFHHCReoHzDABePo8jLwzjeLiS3fdk5Eqtp1SUDSKZ1Ii81q8VjjKTBqHLJeDP9nFFkIhbY8C71wAU7MPb3sShnD9TX6QjLE+OLd85ntm1DGd7LNMN5YB4p8FgcsDOziz0KuuKBOg/nzOz1dw9Bz0ICD8TQDQYRLJgazOPLT95v+RZfPB7gK9KmJAa9wfhnUOCFCChnjSvkWQWKwBiHGuj0kc0X0UWkkeWgjJeL2fmvnBA52w+BER+Vj05FfNJnlG6zjqkoC4WlUzMiF9woWoymCsFBQPVDdZY4nqkWfElH4YLASYxuaDDn8gh5+Zpr/tUXCbhVrevjX/WYIuB2jLOV+A7PZv3iU/lvvXpNIAa9mk+C+C3XVXPXmo/Afi4gC5tVwGOXN8OVjzxpIZF8UiN4kiF/RVmLuxPwP4Vd/YGgAVbX3VMOCrqaAMZ8rnU7+F9BK6wsBSerWy9aa7kWQ9Ht2RFFrXN7mbEgogOtGwdlmbNK0cn+X8Ftv21olaUnDB7ZXBbuhStT756G7yoIdhQ4XMVgKcsFzcG40MXNlzx6htnCZpI/8WYVnSnkEwQt3/+03adsveSJH1DOZanvwCbLKureUXrkRuiSpIhY8uOhdInkcQk0QN6DJ7iqrDItMaNn24FYLQqdFNVXvu6XVYwwW+mGtxtr0I5BfGJTlpyk9EMMD8o6lbohN8Vtbdu8w4C2zkZsC3Jd3cONJ7AXjRj1vtsmYJ90iTMw9qhs7Yz50Qyt5gOQ91oeZsmmCVXF5YQlSlH8ZTxLSWmeZeOO0IzbNprezfOuvOFqSbDhWFtzhP/oQWTqdZ60THeY7tjFIY+qEJsFUEzpDenrVBRL6KMhjdANZLr/J60nF18P0VyFcHCvlUu8C8wfY6JCHYES5sxt8st//5DVdRIuJtwhkNoC0MxIGa9wet/5xKf1VslJvGNEe9FTRGfLGqHFCSnRlCM5/0Kow5FwSvvEfjleHWbaREAyuiXi5u2Zjovx3vGBQXGXxjZ/w0Kr0fc1io59DqEiIX/+hdcYiNKmlPaoCr+xGxVUPqtXI+hugA0nNLzAi2onq5r0D8gxQJ86w/6QXUgIZvFD+mBd2Yv1yict+ItE217W9laUYXQliSaln0CYTfjyAOpM5ICDFDl0kAQmZV0tDuFmqiXgxIPk8jk64VhjWbHd0iOc2FXFPySGFC9olVDuW6yYE4MD+OZdhb7ihPYQfXqZU/Ej85B+Q+ih0TUwWxVoZbl1F3wPKt3TPhCfRy32WQrql5gGU6rUz0TwdW4hySAlu+18/LLdHCJzlc8Zly7nbLCSUO8+tAY8PI8ajZkKHAyWCkvAoxsMZcs1P3HaCI/57iL03pm+KwX9E56FyUgI7c/7CmmR+vkH1n9UHQHJHq9Bjkdb72G2GU+gxA/O+G67rSGtIlAAb7c7g8aZUY/pgHuG07kMCvKPSyv8lCWiaGb1cj4+MnDRBKE9EAD3K293mQOmLyxVwXeBs0hbfh0HxtEqkb+1hC9p47/LpzVoHX4JR0ADMGKdLTCaRvWytHdt74a1Kxno+bKOJRdyVh9GfFsJIulpVxoo0lbnQiB0DHMZRhDfeYZu7xvb8nf4948h5aN/1x2dIuC83ks9soMka24Nd18YdM7+vS/LePgh6GzDIceCCXqqGvmBTChMg1MrT3sgyKlcq7tlvklu/5BuqqI0GS9adn3HHgJjwhdasTtZ7UcafbFFoaVaj9H1vEf67QknXGOC/SicnkO+dfJ7mOFNCrUiI0fZnr5H3gH5t3uHE3OJ0/qmWA6gFlgrGunjRasfUZYwC+y9zDbdjaSv6wkRlJyscKxuLOAGy34ogRKcF+6H0EXLQVoUR+lu6yh05TyuNEXtGDdKOLrr4xphyrTVfWaDZH3oJKBoK5aGHhU7DZsMmYYqYOB214hztfWCrJo0f8pnXMU6invY5o0ouRrrBkov8K+BlyEw8yVOHmFlxB3SRUIuvtf6dpb+A6+LiovLAoEaDHlRoEpIrUdqk0Q9uKTbfkSCsN26oAPHdrZHcXE77QqDRllpa0Sjw1qm6vQtq3e8hitNiepNF86lAChLBJyGcnz2ko0WuT7BzRXoq2uRg67wByg/hxXD9dT4M3SEmhmt19faJgtivZjiXGU3LQCDX3twbF/QuTPfAdTEwlwvUaqr8PJ1z/FGV4KQj6/FPJJBBATqM4i3qCBBGh7bXJ8TojGJOjK8xmJd6GUofqb+8HXrwE+9EV3ZOPbPQJ9swg8vZxoJHCOQ1fOLFi7Vs7ztfA2i+ykMcARDPJiLZDkIdwFyRurJRIRakNo4fHTc6NfgFAlwzFSOF3suNkCWs0awmjJkyNXdEIKq3sT5AsMGNaXRgZIJE3fZoHQ1pVdUyMtV7GJ91MEK4uqg+VRjopYTbPIbbeulq2njZ/TSzzZThUg0B8Q09hxlLBNOi6tctF5UNZSNfmoN0Yi7sbroFlgrdGnHdu4/JjbeMAdaCCY02IKyWRzFyqYMXbjBi9fWCyRt7qDQveoZ/WDL57Dh2z+PkQfxUQ/zWryQS5Gx0l8cZ0sdiUmndtsjDEw6XEkZt4i7pekGltwL6X9H0k3GGT4U+RLi1+6FjJNugZCJwCQXgwOurX7/B1D6JJQFg50Waj2ipwDJcaW+fzLuF+byzfVI2Q5GevA0qrEh1HspID8bPgt9EP+BS/iocPLkJX52wAl951SJd1Ne/oGAFUv5C3HOqtcWQLh/cmApRGtPcw6Wkapwpo8hGwsKDYHBr54tUBroqe6qCg7xenyoYIq0D/S8c8XmIFJ/I3AE5GcRZUsBLSTEIVarvXvyAyJQeBWPRsvE2tTZtMGuxS+20Rqxy232DG7lmgrjLeyY25t+evmDtlS6y2roI+aEoBuGeycqPaoIjDBdd3UnEFNU5U4nkoPbJjMBS9JgEPuLnX7UAKezEb7vUbl1Cj/5TwSXjgGYKpgODs2hA7SvJ1DSuftB29WG6pEqjt4mKHw/cOs1X8PnpEQ6XUIeHSZkM0w8UCWrHJxVFtck/Xcsg3dtk1crzAoVzwO1Grjg731jVNNJrQxk3rV4WdBBfpHCwG7Kk0d4sAyLrxDSOiio6aAnghCvsWRNV0Mz40Fzb/3OzExlNHEwA9YnCZi4nuwbDJiO714okB8QbiRMJRkPCfdU/r0NzytET8xtpI7s5E3Ol8yUrWJj1DNM7gGsxeUG7dD7wGOpA7IYwqWG31525E0y8ZIytZknSLcN35uDHJ8Eym6lqdxRdg/uHLpxUk7SL6Dn+TIe+eii3ubEj90lVL4c2joA5puYslDoTaWrsfEHJ7iyrKGa7g5DHWxkcB995Zk5coL9hSowZASKdWMpQ0HR2Dv/ZnDkO523WXlF0F35vTkIxtjjn48CUXMfzGjmEhKOWACYonLbikFqpvQ/VM0XTPSbmQg7LNw2FUN9itOTb4aOaCb74LC88F++KJ4azDVYVpxXC35bfsqdgK2lngxfFqhMOGEYe73c8l9Ti5gli2PejI6Hm0y90SygCRfiI6fOa2qBoMKOnoLyW4M051d/uz/Q3vRIgo1P0Q+LmgPlLrKjxxWE4Bz8pS3H0OwC4Z93RPMcTCrhAWmxmwSWNNndKUdI+0Cbkfl5NFeccJxVvBNCDiocwbXMMekEFPuotzsvo9lngvUru3K8eFcopeLEGL3jR+UWaJHrk2TrBBkQ0LYWzBJhp+607Jupq/ElEu26yMPKXR6iXUkbPYK8X4grUI47PUy+1LtCHadoazQVT3YrnDkjVausHVJuhSkB8HGf8uvEfustVvOxc7yxkqMj/ThLtVCXKUFbo514Q88t2deE0aslFeC2QXc8dd5MfIrdvDwRXeYAidIUcj4VX5gt2Qcf/54oL6jplPcFRBMhLBc5d0GzkyG+TLqswZywo6duCrgEMf0KJL0FqUoAAsAxpznuCSr2YTMBXza60MnzBFouGOqECR4D2/6+fbtJOUWEuuf3i8zUQqdJVuQHbbOmTX/TWVw14Nbp5gzk3pi6SdGS56VW+/tf30XRCWgIUvvxcIdWWU41PDSyKrTiGhnuMK3H/b4dEm7DaK2lAm82X+Kgodm1uebg4E0ZvcN/xFx28XHAv3hFd0JqpIyLXcLa+ZJMF3cOJqINMgJ/uf1ZZBCHNWbY7AHPm+caqMzXDesYXx1J6lzFEaVuOpTSO2alVO+QxSTNsspNCdV9P4VrdtmCt8uthsLAkDlJuOdxKHzMNcg0X/f+pHKZSCrWEfku9D65SwSVBkTi2pwsK938lkTrSxPJylUfTwMP2x0FSfI2/nVVBJiZlB5mW2JCdW0/gGxtTCfxdIIzg2FvW+mLs0WTZfazUrMbQFFuquta+Gb6Gb+2SPTAaoNXGJPh7K7ZL6VpUTrIhzizjFM0uQXa9r98cf5iVRYwd+rZOA6igLquS9HDW9PTCovyUpCMiaSBVGpaT42g+oRg189L/KBHkjs78sOXhPEq6GW4O9BRotmFpBJgW5MhszrALMyQ0UoXRu6PtzwxBM6fZfcUZiC1EToOB1DBnViKwFtCLUXiZWQqZubJvIniUFR0iltSENPRFEystHmLOyusYIsyFK37PGaY2bC6GuSkAKZ4uC6i+qmPeroh3Q1nygH8FXRZsrURAnxmupwMNuz0woWtbK+y5X5L3hypaAU3Hbhj0hJlJkkpZtplYAhNKuHByrdOn2A/+0Ls1kn++XZJoZfM//Ig0i3PR/d/08dGitolRuULJHrdZvVsGHSIj8XjQZqGKcMlI6C20OrU6wytTx5GuINb/6XglyLCLUAl9vPzIz6xay+tdR9FywQhTDedF/Y7JboQl7/RRSYk35ungaCIDTdh8OwqMJj/uFKrWYFRSJ9GZyU/trS3+R+1mV8M28KGNBv/xe/751MjEaC5bex/tcoO1IiM22vhOdFQe591EVGYw6NwJw2Sfk9nFnZFNGLEVncVbgH+7KE142Ekx/GcXUHq0AxwdfLx/cbRek2T/Vk4Q3vkYOSXmk6FqbuKddTv/z/Z5EF4LMV0OrJvIkepmPTpHX8PP1gEMn2nwsd6azE0ql2KO6nh1SN5UIFvdtJFuh6f2I2NsBkbG6lpQ+y+zUIGjn4KYqeSS5bMvk0rrADmR5HjxI9H6VH8GKWkThx38o3AzcMP08yelp4GZS1tJbiuXfLoOFjBoyFnf+0vOmXmzrbn+xBtIoWmBT1eP1E1tsJGOKLlLv42nMdd6glcxhx/NkK9tInZgYkrlz5q4ENQqbwgYAZe6a1fcKkPWXpqJLDMSlfFtc3f5E0kfYxbDYKY+rH0PZH2RPzrpOu6N7SaXrNoDPFw+iST6e6OeG10Hw4I6QzPPTY4yqFTP5/ec/wXu29bVhVcNgnYPddBo8dh0682XdpSMlLzJQez88fb56smkUlxIVpCBAojB/UlyTVtxEk6IDD91mVPrILdLHX5epz4QXUWx2VUOH2zpV2zZHIZZH+0RVupo13g9hirIzGobxfYTAm+no0p572sxAjUCgPiMC3Zz6Ks+qrWLilGMIhMYrdKk+r3H5PxyN81BPx7vErZwuSfCk3PptawcEvnDaP04XgbZ1udyCG45MUOzqdW0wBxj1MVyP06NU5n6ZBU626RFnO0qsCA3oCiTbTs+QAH3QOQ9sQDGqk8ylCzVpDSrhvctRwJBw2as924DZP8fhCTI1svc/c8+LJqsIfAR6ZdzIBGa/zhBTrDSZm+zlI4zHK0UZDLVW/DM0SXy05cfhtgdWIN2mXrSsDy45pDPwuOi4x5NJVAfLRkKAZCF08BS8uj4PfzX+slOb/sCmMgRt5VKIUdKxkkbTW6fzSwruemdIX+N/CPpkKr8TAg9/BpD4Up5thQWmO35GI3QFwZsz8yzHsqLc+ooQ1p6Uf31Cd03t6K1zk7yEet2EzcnZOOBliw5wZC7pBAVCZ31nKDWBRb3G58C35NZ87AAgQTLFF5XJ+VX4ADPVfrtIbB/YQf5ok76Te6Nybei+MPH3zo/3oG74+Y3J3ShYmigN4TvU9Jqurn9n9MslVyd/nil3pfRv3JElLKYTPe3n8sQl/W+pvwFayXEZSbiyEq0CKC7yQKER4dFkU9AciEMAAI1q6mbgQSc3uZEwaKTQvenTv7Cn1V0BFESuhCAImxmtCiSLtFHDwaoBXweoFp8h3lzMVYUatT34LuZ2Sfzjm62iC5loxdxydV2AdYLeX9tmmln0ineBqUXB5rXYchRxPWvZzGGQDhlX36k+qd9J32F1FAdWxrUUducpzEv8ePpEKXsLhGF++6g0Q2m2yADVX4IVxgol2XfiQiqqTqh8fmALto5VRrTfC9rXIAAJcOYV/xhLD6sBNevLASLGq1Ssq8FBHRdaR8PZ8jZkvleO8gXov9XEaG7Z0CXaiIuG/Y5PhvXFT0pDs+r4PaLi+c+xIhZX3e4sjDnmBzmy8t7eeGGPX6dQhzvTfV4qcQzXqytz10uc+WMX08Mnr2fIwaND97KbqXvX9DlH5DWptdFOMeXq5Fw4dhVd+VAWYi7N0g/4/0PI0KmYoupNbsL3jTUB7+hF3fkY5/8o09HBxJ+Y45hfElxpluO86Uwi4fQivFeKvSGIzLlALjjcuCkljFC+VbY/NRv00Z0Mv+GakDsOHedBez5WlNC2f3CpzHfU5avFpNBQsyPBnJPaUfLrMje9P3qhyNsoMNBptOPSauBK2zw5mvw97BV1+4UlgAaORB3lLW6O2VYkVTh1U3WvTmJcUwkOn5jJaKSrlDKd48XR+il5vmmYrn5pdrjMTNTYMrQKCBAGrOzlqTuuGDE71DFHOlBZegUiRDOejyv1rKwePFzqSXjsbmYz86HKu3IF1F45stD3yqRudxHwXUl5rIr67I6TRnrx0u+BlD2+wb3A/sIqgqGEVm2EM/MtGCQ+KlWxzhi/jTKnVXE+V3Yb3+ub3qEGnXmj0B/zvVmEYiw16mGYgq9gXw9bJirxOzmP2X5Dd1uDWd1oJcKjmzr4aEgTT6qQ5bd25Ry/TxxB3bU1moqHdM84naQ4M48q7z94kOh/5Zemxz3a5a3Sv8d3rBLnJY/QuWFzXnBBEOxYNlryJ03VKhvRYFqHKTiEZYUz74AHBisnwoJa3qZ917dis5C3ld9TUaEZjsVeIMZhOFBe++47d8P98O8fLhWZeMz2Ti9E2x/c7OfPPv3kTI7Aw6mPHAwmMGf1PgtQziz9Whw/9IPSHsdnvqO4SUI747u3jZpola/fhKMlDiIjNc2o0nYQNSNOvQZTqq9kjei3gLM/AwFD/jLaE96RZJxg0RhyAeNS5bd39DyYJyNAGwZe6HqnAZQMtXoditaYp03OOf/zwskxI2hWvkqGwQzKIhlkb2uZBJMYBfvo4juVEL1BoZWKXfngUCkCCLeXH7hIdnjC+yHBU2pGfkZS2Zka5VJNXwx+0wG4uZFOd1t1ftYfvHh1nR3ej7ZHjtAZb5ZWrqEuyYW5y/0GfALD8tJ5zTDzQNQiXQmFv4lNr3KAXJGkLmlvD3c1YjZ2ySaLmzGijr3lqpfK4nZxeV+K4KapskbI0qI5E+SusD4trwO0Q1gopVMQt0IuWs0F4mZf7xg5Ly24Nb4P1Kqy8mG8fwaYsB6CPvr8WYRWqjypmTTyKuou5wlSOUq2QRyVQoBiEGwzUSPHduCDhxVGsZZJUokE0fSfRKsHDMpDVfMcnbzyUVkeBRp9q770sP1UgWhP0Ym6abxDHA1q/MuUINeJbyINpZWkaK80kPVuDMSifMgWnp9Hu+7HsJEseNtNrPGWzSmclAL7bQhkdcjNKRustrL1/xSDNW1/QGG3J7OIX95UmwCNLweHK1PnJvry1bvrgHRqLRj4bs4wepeLZ5SsaoKpaX1O0M/47g9xvHMKvUSa81F2DbQKSMgQieFozYAKlmbKlQe95h19xTWVJl3mpT50rfTef1KyORxWxWgwtueCsEXGnfkyoHiLQA+toUmjuxbV1zjRDOc5Pgy4W9HfBKV3A3i65nVt2RIA00dtiVon1+JpYxTGxMb/PtzR1Q8yB9huLYDMToKCM8XC+lWd9JSG9AuA8vupJsgYat15K0/1/eeToSlLQZuE4qD7Poq5Pq810U9A8K3/8fuWpPVpSHo6+r6xahrjs9+exhl7Px87CHrs95cLS9RzCqLnRQ7KDqow+FrrHXkjpKDPrgoycNh2cCA2/HcV5MGBWnA4J6tNrjb74V3gJcvqd/QhdxM3xmS4AQ","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"1382e8398b0a592ec7f3d454b60c5c568f0e3a3b","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"6b7f83bda6f7c3fe014d52428b31af1638daa6cc","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file From b8b0f2d557de4856fd7ac9ab3a43d0f8b1a935f9 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 22:57:26 +1000 Subject: [PATCH 26/95] docs: name strict relationship parser --- .../en/content/Core Services/ResourceCalculationService.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md index 06caf82..6febf97 100644 --- a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md +++ b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md @@ -226,7 +226,7 @@ Behavior: - pterodactylGet(): Centralized HTTP call with retry on connection errors, rate limit detection, and sanitized error messages. - pterodactylGetPaginatedData(): Paginates through Pterodactyl lists. - getPendingReservations()/getPendingReservationsForNodes(): Sums pending reservations by node to subtract from available resources. -- extractRelationshipData(): Normalizes relationship payloads from Pterodactyl. +- requireRelationshipData(): Requires an array relationship payload and distinguishes a genuinely absent relationship from a present but malformed container or data value. Integration with reservation system: - Pending reservations are read from the local DB and subtracted from available resources to prevent overselling. From 87f21b8b71a7920ccfb6ca33b9051460ff090f13 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 23:11:46 +1000 Subject: [PATCH 27/95] docs: require full safety rebase --- .qoder/repowiki/en/content/Deployment.md | 2 +- 02-SERVICES.md | 5 +++-- PROGRESS.md | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index 8dcea68..4fa2b01 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -144,7 +144,7 @@ Operational requirements: - Scheduler must be running to execute cleanup and alert checks. - Database must support transactions and pessimistic locking. - Network access to the Pterodactyl Panel API must be allowed from the Paymenter host. -- Node payloads must provide an integer `cpu_threads` capacity value; missing, fractional, or malformed node/server capacity fields and incomplete pagination fail closed instead of advertising unverified capacity. Stock Pterodactyl does not expose this node field. Keep deployment paused until PR #22's explicit local `NodeCapacityPolicy` is rebased onto this reconciliation (or an equivalent trusted capacity source is installed). +- Node payloads must provide an integer `cpu_threads` capacity value; missing, fractional, or malformed node/server capacity fields and incomplete pagination fail closed instead of advertising unverified capacity. Stock Pterodactyl does not expose this node field and uses zero server limits to mean unlimited, while this branch does not yet encrypt/migrate the stored API key. Keep deployment paused until PR #22 is fully rebased so its `NodeCapacityPolicy`, zero-as-unlimited rejection, and API-key encryption migration are all retained alongside every PR #23 safety and Wiki change. A partial CPU-only cherry-pick is not deployable. **Section sources** - [DynamicPterodactyl.php:48-75](file://DynamicPterodactyl.php#L48-L75) diff --git a/02-SERVICES.md b/02-SERVICES.md index aea9be9..ce7a06f 100644 --- a/02-SERVICES.md +++ b/02-SERVICES.md @@ -101,8 +101,9 @@ class ResourceCalculationService // resource shapes before calculating totals. The fetch layer also // rejects duplicate node, server, and location identities so repeated // upstream records cannot distort capacity. Stock Pterodactyl has no - // node CPU-capacity field, so cpu_threads remains a fail-closed gate - // until the explicit local NodeCapacityPolicy is rebased from PR #22. + // node CPU-capacity field, so cpu_threads remains a fail-closed gate. + // Production also requires PR #22's zero-as-unlimited rejection and + // API-key encryption migration; the full PR must be safely rebased. return $this->buildNodeAvailabilityFromServers($node, $servers, $pendingReservations); } diff --git a/PROGRESS.md b/PROGRESS.md index 4c2e31d..7ed42cf 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -71,8 +71,8 @@ All dp-NN backlog items are implemented. The active reconciliation is staged on **Working on**: Draft PR #23 reconciliation and Wiki verification **Status**: Panel changes are preserved on the reconciliation branch; Qoder Wiki pages are migrated to GitHub Wiki and refreshed for the final batched location API flow. **Current file**: PROGRESS.md -**Next action**: Complete exact-SHA review, then rebase PR #22's explicit `NodeCapacityPolicy` onto this reconciliation before any production merge or deployment. Resume Mutagen only as a separately authorized deployment step. -**Blockers**: Stock Pterodactyl does not expose node CPU capacity, so PR #23 must not deploy alone. PR #22 overlaps this reconciliation and must be rebased while preserving the hardened test guard, sanitized errors, and Wiki changes. No CI checks are configured on PR #23. +**Next action**: Complete exact-SHA review, then fully rebase PR #22 onto this reconciliation before any production merge or deployment. The rebase must retain its explicit `NodeCapacityPolicy`, rejection of Pterodactyl's zero-as-unlimited resource limits, and API-key encryption migration while preserving every PR #23 safety and Wiki change. Resume Mutagen only as a separately authorized deployment step. +**Blockers**: PR #23 must not deploy alone. Stock Pterodactyl does not expose node CPU capacity, uses zero resource limits to mean unlimited, and this branch does not yet encrypt/migrate the stored API key. PR #22 supplies all three protections but overlaps this reconciliation, so it must be fully rebased rather than partially cherry-picked or merged unchanged. No CI checks are configured on PR #23. ### This Session's Changes: From 3202e2c43cd8a3b7b55f6bda289fa0cf8cd5f98f Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 17 Aug 2026 23:44:09 +1000 Subject: [PATCH 28/95] docs: repair qoder source anchors --- .../en/content/API Reference/API Reference.md | 20 +++---- .../Admin API Endpoints.md | 4 +- .../Availability Endpoints.md | 2 +- .../Public API Endpoints.md | 2 +- .../Reservation Endpoints.md | 16 ++--- .qoder/repowiki/en/content/Admin Interface.md | 38 ++++++------ .../Companion Extension Pattern.md | 20 +++---- .../Service Layer Design/Alert Service.md | 10 ++-- .../Node Selection Service.md | 8 +-- .../Service Layer Design.md | 18 +++--- .../Supporting Services.md | 12 ++-- .../Core Services/ConfigOptionSetupService.md | 4 +- .../ResourceCalculationService.md | 6 +- .../SliderConfigReaderService.md | 4 +- .../Database Schema/Database Schema.md | 4 +- ...Model Relationships and Eloquent Models.md | 58 +++++++++---------- .../Resource Reservations Table.md | 38 ++++++------ .qoder/repowiki/en/content/Getting Started.md | 2 +- .qoder/repowiki/en/content/Testing.md | 26 ++++----- 19 files changed, 146 insertions(+), 146 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index 47f13f5..8d0c7d9 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -59,7 +59,7 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] - [routes/api.php:17-40](file://routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-41](file://routes/api.php#L1-L41) +- [routes/api.php:1-41](file://routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -70,10 +70,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] **Section sources** - [AvailabilityController.php:9-70](file://Http/Controllers/Api/AvailabilityController.php#L9-L70) -- [PricingController.php:12-158](file://Http/Controllers/Api/PricingController.php#L12-L158) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L138) -- [AdminCapacityController.php:8-63](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L63) -- [AdminReservationController.php:9-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L76) +- [PricingController.php:12-158](file://Http/Controllers/Api/PricingController.php#L12-L157) +- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminCapacityController.php:8-63](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) +- [AdminReservationController.php:9-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) ## Architecture Overview The API integrates with Paymenter core models and services and with the Pterodactyl panel via HTTP. Services encapsulate business logic and data aggregation. @@ -204,7 +204,7 @@ Important: **Section sources** - [routes/api.php:17-22](file://routes/api.php#L17-L22) -- [PricingController.php:24-158](file://Http/Controllers/Api/PricingController.php#L24-L158) +- [PricingController.php:24-158](file://Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](file://Http/Requests/StoreReservationRequest.php#L38-L112) #### Reservations @@ -288,8 +288,8 @@ Notes: **Section sources** - [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:24-138](file://Http/Controllers/Api/ReservationController.php#L24-L138) -- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L163) +- [ReservationController.php:24-138](file://Http/Controllers/Api/ReservationController.php#L24-L137) +- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) - [ResourceReservationPolicy.php:25-58](file://Policies/ResourceReservationPolicy.php#L25-L58) @@ -318,7 +318,7 @@ Notes: **Section sources** - [routes/api.php:32-40](file://routes/api.php#L32-L40) -- [AdminCapacityController.php:17-63](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L63) +- [AdminCapacityController.php:17-63](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) #### Admin Reservations @@ -353,7 +353,7 @@ Notes: **Section sources** - [routes/api.php:32-40](file://routes/api.php#L32-L40) -- [AdminReservationController.php:18-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L76) +- [AdminReservationController.php:18-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) ## Dependency Analysis diff --git a/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md b/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md index 97fd20b..b356ffd 100644 --- a/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md @@ -349,10 +349,10 @@ RESOURCE_RESERVATION ||--o| SERVICE : "service_id" ``` **Diagram sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L66) +- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) **Section sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L66) +- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) ## Dependency Analysis - Admin controllers depend on services: diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md index c0ce99d..e85607b 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md @@ -215,7 +215,7 @@ ForEachNode --> |No| ReturnData["Return {location_id, nodes[], max_available, to ``` **Diagram sources** -- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-67) +- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) - [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) **Section sources** diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md index 26ae260..4a1f07c 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md @@ -80,7 +80,7 @@ ResSvc --> DB["Database (ptero_resource_reservations)"] - [Http/Controllers/Api/ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) - [Http/Requests/StoreReservationRequest.php:38-113](file://Http/Requests/StoreReservationRequest.php#L38-L113) - [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Models/ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L66) +- [Models/ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) - [Policies/ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) ## Architecture Overview diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Reservation Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Reservation Endpoints.md index 79b8941..708ceb5 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Reservation Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Reservation Endpoints.md @@ -48,8 +48,8 @@ Controller --> Policy["ResourceReservationPolicy"] **Diagram sources** - [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L138) -- [ReservationService.php:43-454](file://Services/ReservationService.php#L43-L454) +- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [ReservationService.php:43-454](file://Services/ReservationService.php#L43-L453) - [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) **Section sources** @@ -73,7 +73,7 @@ Key responsibilities: - [routes/api.php:24-30](file://routes/api.php#L24-L30) - [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) - [StoreReservationRequest.php:31-113](file://Http/Requests/StoreReservationRequest.php#L31-L113) -- [ReservationService.php:43-454](file://Services/ReservationService.php#L43-L454) +- [ReservationService.php:43-454](file://Services/ReservationService.php#L43-L453) - [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) - [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) @@ -380,15 +380,15 @@ Service --> DB["Database"] **Diagram sources** - [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L138) -- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L163) +- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L162) - [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L454) +- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) **Section sources** - [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L138) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L454) +- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) ## Performance Considerations - Pessimistic locking: Uses lockForUpdate to prevent concurrent modifications during node selection and reservation creation. diff --git a/.qoder/repowiki/en/content/Admin Interface.md b/.qoder/repowiki/en/content/Admin Interface.md index 31c00c0..945ee2a 100644 --- a/.qoder/repowiki/en/content/Admin Interface.md +++ b/.qoder/repowiki/en/content/Admin Interface.md @@ -89,10 +89,10 @@ AL --> ALS - [AuditLogPage.php:15-29](file://Admin/Pages/AuditLogPage.php#L15-L29) - [ReservationResource.php:15-27](file://Admin/Resources/ReservationResource.php#L15-L27) - [AlertConfigResource.php:27-39](file://Admin/Resources/AlertConfigResource.php#L27-L39) -- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L104) -- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L110) -- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L6) -- [audit-log.blade.php:1-48](file://resources/views/admin/audit-log.blade.php#L1-L48) +- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L103) +- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L109) +- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L5) +- [audit-log.blade.php:1-48](file://resources/views/admin/audit-log.blade.php#L1-L47) - [ResourceCalculationService.php:10-22](file://Services/ResourceCalculationService.php#L10-L22) - [ReservationService.php:16-35](file://Services/ReservationService.php#L16-L35) - [AuditLogService.php:10-41](file://Services/AuditLogService.php#L10-L41) @@ -115,13 +115,13 @@ AL --> ALS **Section sources** - [Dashboard.php:27-73](file://Admin/Pages/Dashboard.php#L27-L73) -- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L104) +- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L103) - [NodeMonitoring.php:22-61](file://Admin/Pages/NodeMonitoring.php#L22-L61) -- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L110) +- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L109) - [SetupWizard.php:50-427](file://Admin/Pages/SetupWizard.php#L50-L427) -- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L6) +- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L5) - [AuditLogPage.php:31-103](file://Admin/Pages/AuditLogPage.php#L31-L103) -- [audit-log.blade.php:1-48](file://resources/views/admin/audit-log.blade.php#L1-L48) +- [audit-log.blade.php:1-48](file://resources/views/admin/audit-log.blade.php#L1-L47) - [ReservationResource.php:34-127](file://Admin/Resources/ReservationResource.php#L34-L127) - [AlertConfigResource.php:41-176](file://Admin/Resources/AlertConfigResource.php#L41-L176) @@ -176,12 +176,12 @@ ShowErr --> Render **Diagram sources** - [Dashboard.php:27-73](file://Admin/Pages/Dashboard.php#L27-L73) -- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L104) +- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L103) - [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) **Section sources** - [Dashboard.php:27-115](file://Admin/Pages/Dashboard.php#L27-L115) -- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L104) +- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L103) ### Node Monitoring - Purpose: Real-time view of node utilization and availability per location. @@ -208,11 +208,11 @@ NM-->>Admin : Render table with utilization **Diagram sources** - [NodeMonitoring.php:22-61](file://Admin/Pages/NodeMonitoring.php#L22-L61) - [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L110) +- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L109) **Section sources** - [NodeMonitoring.php:22-61](file://Admin/Pages/NodeMonitoring.php#L22-L61) -- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L110) +- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L109) ### Setup Wizard - Purpose: Configure dynamic slider options for a selected product, including pricing models and allowed locations. @@ -239,11 +239,11 @@ G --> |Yes| I["Success Notification & Reset Form"] **Diagram sources** - [SetupWizard.php:50-427](file://Admin/Pages/SetupWizard.php#L50-L427) -- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L6) +- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L5) **Section sources** - [SetupWizard.php:50-509](file://Admin/Pages/SetupWizard.php#L50-L509) -- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L6) +- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L5) ### Audit Log Viewer - Purpose: Track administrative actions and display recent alert delivery failures. @@ -274,7 +274,7 @@ AuditLogPage --> AuditLog : "queries" **Section sources** - [AuditLogPage.php:31-103](file://Admin/Pages/AuditLogPage.php#L31-L103) -- [audit-log.blade.php:1-48](file://resources/views/admin/audit-log.blade.php#L1-L48) +- [audit-log.blade.php:1-48](file://resources/views/admin/audit-log.blade.php#L1-L47) ### Reservation Management Resource - Purpose: Manual intervention for pending reservations (extend TTL, cancel) and bulk cleanup of expired ones. @@ -433,10 +433,10 @@ The Filament 4 admin interface provides a comprehensive operational view of syst - Extensibility: Add custom columns, filters, or actions in resources; customize views with standard Blade patterns. **Section sources** -- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L104) -- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L110) -- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L6) -- [audit-log.blade.php:1-48](file://resources/views/admin/audit-log.blade.php#L1-L48) +- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L103) +- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L109) +- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L5) +- [audit-log.blade.php:1-48](file://resources/views/admin/audit-log.blade.php#L1-L47) ### Integration Points - Pterodactyl API: diff --git a/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md b/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md index 3d9d4df..2decfce 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md @@ -84,12 +84,12 @@ G --> M["Admin Recipients"] **Section sources** - [DynamicPterodactyl.php:48-127](file://DynamicPterodactyl.php#L48-L127) -- [Services/ReservationService.php:16-454](file://Services/ReservationService.php#L16-L454) +- [Services/ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) - [Services/ResourceCalculationService.php:10-545](file://Services/ResourceCalculationService.php#L10-L545) -- [Services/AlertService.php:19-393](file://Services/AlertService.php#L19-L393) -- [Services/SliderConfigReaderService.php:7-69](file://Services/SliderConfigReaderService.php#L7-L69) -- [Listeners/CartItemCreatedListener.php:11-174](file://Listeners/CartItemCreatedListener.php#L11-L174) -- [Listeners/InvoicePaidListener.php:12-136](file://Listeners/InvoicePaidListener.php#L12-L136) +- [Services/AlertService.php:19-393](file://Services/AlertService.php#L19-L392) +- [Services/SliderConfigReaderService.php:7-69](file://Services/SliderConfigReaderService.php#L7-L68) +- [Listeners/CartItemCreatedListener.php:11-174](file://Listeners/CartItemCreatedListener.php#L11-L173) +- [Listeners/InvoicePaidListener.php:12-136](file://Listeners/InvoicePaidListener.php#L12-L135) ## Architecture Overview The extension follows a companion pattern: @@ -245,11 +245,11 @@ IPay->>IPay : notifyShortfall on failure **Diagram sources** - [Listeners/CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [Listeners/InvoicePaidListener.php:14-136](file://Listeners/InvoicePaidListener.php#L14-L136) +- [Listeners/InvoicePaidListener.php:14-136](file://Listeners/InvoicePaidListener.php#L14-L135) **Section sources** -- [Listeners/CartItemCreatedListener.php:13-174](file://Listeners/CartItemCreatedListener.php#L13-L174) -- [Listeners/InvoicePaidListener.php:14-136](file://Listeners/InvoicePaidListener.php#L14-L136) +- [Listeners/CartItemCreatedListener.php:13-174](file://Listeners/CartItemCreatedListener.php#L13-L173) +- [Listeners/InvoicePaidListener.php:14-136](file://Listeners/InvoicePaidListener.php#L14-L135) ### Pricing Coexistence: Native Slider Metadata Only - SliderConfigReaderService reads dynamic_slider ConfigOption metadata (min, max, step, default, unit, display_unit, display_divisor, pricing model/rates) for frontend consumption. @@ -270,7 +270,7 @@ SliderConfigReaderService --> ConfigOption : "reads metadata" ``` **Diagram sources** -- [Services/SliderConfigReaderService.php:7-69](file://Services/SliderConfigReaderService.php#L7-L69) +- [Services/SliderConfigReaderService.php:7-69](file://Services/SliderConfigReaderService.php#L7-L68) **Section sources** - [Services/SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) @@ -353,7 +353,7 @@ Common issues and diagnostics: - Alert delivery failures: check AlertService sendNotifications and delivery logs; ensure email/webhook channels are configured and recipients exist. **Section sources** -- [Listeners/InvoicePaidListener.php:58-136](file://Listeners/InvoicePaidListener.php#L58-L136) +- [Listeners/InvoicePaidListener.php:58-136](file://Listeners/InvoicePaidListener.php#L58-L135) - [Services/ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) - [Services/ReservationService.php:125-141](file://Services/ReservationService.php#L125-L141) - [Services/AlertService.php:128-248](file://Services/AlertService.php#L128-L248) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Alert Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Alert Service.md index 6a5b778..deadc8d 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Alert Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Alert Service.md @@ -75,14 +75,14 @@ AlertSvc --> Event["AlertDeliveryFailed event"] - Admin AlertConfigResource: Filament resource exposing CRUD and a “Test” action to send a sample alert. **Section sources** -- [AlertService.php:19-393](file://Services/AlertService.php#L19-L393) +- [AlertService.php:19-393](file://Services/AlertService.php#L19-L392) - [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) - [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) - [CapacityAlertNotification.php:10-47](file://Notifications/CapacityAlertNotification.php#L10-L47) - [ReservationShortfallNotification.php:10-40](file://Notifications/ReservationShortfallNotification.php#L10-L40) - [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) - [AlertConfigObserver.php:8-69](file://Models/Observers/AlertConfigObserver.php#L8-L69) -- [AlertConfigResource.php:150-197](file://Admin/Resources/AlertConfigResource.php#L150-L197) +- [AlertConfigResource.php:150-197](file://Admin/Resources/AlertConfigResource.php#L150-L196) ## Architecture Overview The service is invoked by a scheduled task registered during extension boot. For each active alert configuration, it determines the scope (global or specific location), fetches current availability from Pterodactyl via ResourceCalculationService, evaluates memory and disk utilization against configured warning/critical thresholds, and dispatches notifications if any thresholds are breached. Cooldown prevents repeated alerts within a configured window. Delivery attempts are recorded, and failures emit an event for downstream handling. @@ -216,7 +216,7 @@ Migration highlights: **Section sources** - [DynamicPterodactyl.php:118-126](file://DynamicPterodactyl.php#L118-L126) -- [AlertConfigResource.php:150-197](file://Admin/Resources/AlertConfigResource.php#L150-L197) +- [AlertConfigResource.php:150-197](file://Admin/Resources/AlertConfigResource.php#L150-L196) - [AlertConfigObserver.php:12-69](file://Models/Observers/AlertConfigObserver.php#L12-L69) ## Dependency Analysis @@ -261,7 +261,7 @@ AlertService --> AlertDeliveryFailed : "dispatches on failure" ``` **Diagram sources** -- [AlertService.php:19-393](file://Services/AlertService.php#L19-L393) +- [AlertService.php:19-393](file://Services/AlertService.php#L19-L392) - [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) - [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) - [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) @@ -270,7 +270,7 @@ AlertService --> AlertDeliveryFailed : "dispatches on failure" - [AlertDeliveryFailed.php:9-16](file://Events/AlertDeliveryFailed.php#L9-L16) **Section sources** -- [AlertService.php:19-393](file://Services/AlertService.php#L19-L393) +- [AlertService.php:19-393](file://Services/AlertService.php#L19-L392) - [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) ## Performance Considerations diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md index 96a84ee..44eb7bd 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md @@ -50,8 +50,8 @@ RCSvc --> DB **Section sources** - [NodeSelectionService.php:1-88](file://Services/NodeSelectionService.php#L1-L88) - [ResourceCalculationService.php:1-545](file://Services/ResourceCalculationService.php#L1-L545) -- [ReservationService.php:1-454](file://Services/ReservationService.php#L1-L454) -- [ResourceReservation.php:1-66](file://Models/ResourceReservation.php#L1-L66) +- [ReservationService.php:1-454](file://Services/ReservationService.php#L1-L453) +- [ResourceReservation.php:1-66](file://Models/ResourceReservation.php#L1-L65) ## Core Components - NodeSelectionService: Selects the best node using weighted headroom scoring and filters out unsuitable nodes (maintenance mode or insufficient resources). @@ -257,11 +257,11 @@ Pending --> Cancelled : "cancel(token)" ``` **Diagram sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L66) +- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) - [2026_04_22_000001_drop_released_from_reservation_status.php:8-19](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L19) **Section sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L66) +- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) - [2026_04_22_000001_drop_released_from_reservation_status.php:8-19](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L19) ## Dependency Analysis diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md index 6559184..dc14f03 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md @@ -72,11 +72,11 @@ ResCalcSvc --> DB **Section sources** - [ResourceCalculationService.php:10-222](file://Services/ResourceCalculationService.php#L10-L222) - [NodeSelectionService.php:5-86](file://Services/NodeSelectionService.php#L5-L86) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L454) -- [AlertService.php:19-393](file://Services/AlertService.php#L19-L393) +- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) +- [AlertService.php:19-393](file://Services/AlertService.php#L19-L392) - [AvailabilityController.php:9-71](file://Http/Controllers/Api/AvailabilityController.php#L9-L71) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L138) -- [AdminCapacityController.php:8-63](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L63) +- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminCapacityController.php:8-63](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) ## Architecture Overview The service layer enforces strict boundaries: @@ -226,7 +226,7 @@ end **Section sources** - [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) - [ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) -- [ReservationService.php:387-454](file://Services/ReservationService.php#L387-L454) +- [ReservationService.php:387-454](file://Services/ReservationService.php#L387-L453) ### AlertService Responsibilities: @@ -300,11 +300,11 @@ AdminCapacityController --> ResourceCalculationService : "uses" **Diagram sources** - [NodeSelectionService.php:5-86](file://Services/NodeSelectionService.php#L5-L86) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L454) -- [AlertService.php:19-393](file://Services/AlertService.php#L19-L393) +- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) +- [AlertService.php:19-393](file://Services/AlertService.php#L19-L392) - [AvailabilityController.php:9-71](file://Http/Controllers/Api/AvailabilityController.php#L9-L71) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L138) -- [AdminCapacityController.php:8-63](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L63) +- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminCapacityController.php:8-63](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) **Section sources** - [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Supporting Services.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Supporting Services.md index 6873bd6..d0a0c2c 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Supporting Services.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Supporting Services.md @@ -72,12 +72,12 @@ A --> I - [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) **Section sources** -- [AuditLogService.php:1-83](file://Services/AuditLogService.php#L1-L83) -- [ConfigOptionSetupService.php:1-260](file://Services/ConfigOptionSetupService.php#L1-L260) -- [SliderConfigReaderService.php:1-69](file://Services/SliderConfigReaderService.php#L1-L69) -- [PricingController.php:1-158](file://Http/Controllers/Api/PricingController.php#L1-L158) -- [AuditLogPage.php:1-105](file://Admin/Pages/AuditLogPage.php#L1-L105) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:1-55](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L1-L55) +- [AuditLogService.php:1-83](file://Services/AuditLogService.php#L1-L82) +- [ConfigOptionSetupService.php:1-260](file://Services/ConfigOptionSetupService.php#L1-L259) +- [SliderConfigReaderService.php:1-69](file://Services/SliderConfigReaderService.php#L1-L68) +- [PricingController.php:1-158](file://Http/Controllers/Api/PricingController.php#L1-L157) +- [AuditLogPage.php:1-105](file://Admin/Pages/AuditLogPage.php#L1-L104) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:1-55](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L1-L54) ## Core Components - AuditLogService: Provides methods to log actions and retrieve filtered logs. Captures user context, request metadata, and before/after values for changes. diff --git a/.qoder/repowiki/en/content/Core Services/ConfigOptionSetupService.md b/.qoder/repowiki/en/content/Core Services/ConfigOptionSetupService.md index bed9ce6..f13a6ee 100644 --- a/.qoder/repowiki/en/content/Core Services/ConfigOptionSetupService.md +++ b/.qoder/repowiki/en/content/Core Services/ConfigOptionSetupService.md @@ -50,8 +50,8 @@ H["StoreReservationRequest"] --> C - [StoreReservationRequest.php:75-140](file://Http/Requests/StoreReservationRequest.php#L75-L140) **Section sources** -- [ConfigOptionSetupService.php:1-260](file://Services/ConfigOptionSetupService.php#L1-L260) -- [SliderConfigReaderService.php:1-69](file://Services/SliderConfigReaderService.php#L1-L69) +- [ConfigOptionSetupService.php:1-260](file://Services/ConfigOptionSetupService.php#L1-L259) +- [SliderConfigReaderService.php:1-69](file://Services/SliderConfigReaderService.php#L1-L68) ## Core Components - ConfigOptionSetupService: Creates/updates dynamic_slider ConfigOptions for memory, CPU, disk, and optionally Location; validates pricing metadata; audits setup runs. diff --git a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md index 6febf97..4a01018 100644 --- a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md +++ b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md @@ -76,7 +76,7 @@ Responsibilities summary: - [ResourceCalculationService.php:26-222](file://Services/ResourceCalculationService.php#L26-L222) - [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) - [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L66) +- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) ## Architecture Overview The service uses a thin HTTP client wrapper around Pterodactyl’s Application API with retries on transient connection errors, strict timeouts, and sanitized error propagation. For cluster-wide snapshots, it batches node and server data retrieval to reduce API calls while preserving accuracy. @@ -286,9 +286,9 @@ ResourceCalculationService --> ResourceReservation : "reads pending" **Diagram sources** - [ResourceCalculationService.php:10-545](file://Services/ResourceCalculationService.php#L10-L545) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L454) +- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) - [NodeSelectionService.php:5-88](file://Services/NodeSelectionService.php#L5-L88) -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L66) +- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) ## Dependency Analysis - External dependency: Pterodactyl Application API via HTTP client diff --git a/.qoder/repowiki/en/content/Core Services/SliderConfigReaderService.md b/.qoder/repowiki/en/content/Core Services/SliderConfigReaderService.md index 115e5b6..e4e0f43 100644 --- a/.qoder/repowiki/en/content/Core Services/SliderConfigReaderService.md +++ b/.qoder/repowiki/en/content/Core Services/SliderConfigReaderService.md @@ -239,7 +239,7 @@ ConfigOptionSetupService --> ConfigOption : "creates/updates" **Section sources** - [ConfigOptionSetupService.php:117-171](file://Services/ConfigOptionSetupService.php#L117-L171) - [07-PRICING-MODELS.md:31-53](file://07-PRICING-MODELS.md#L31-L53) -- [07-PRICING-MODELS.md:290-330](file://07-PRICING-MODELS.md#L290-L330) +- [07-PRICING-MODELS.md:290-330](file://07-PRICING-MODELS.md#L290-L329) ### Example Slider Configuration Structures Typical structures produced by the service for frontend consumption: @@ -377,4 +377,4 @@ SliderConfigReaderService provides a clean, read-only interface to dynamic slide **Section sources** - [PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) -- [07-PRICING-MODELS.md:290-330](file://07-PRICING-MODELS.md#L290-L330) \ No newline at end of file +- [07-PRICING-MODELS.md:290-330](file://07-PRICING-MODELS.md#L290-L329) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Database Schema/Database Schema.md b/.qoder/repowiki/en/content/Database Schema/Database Schema.md index bba6e65..b8c83b4 100644 --- a/.qoder/repowiki/en/content/Database Schema/Database Schema.md +++ b/.qoder/repowiki/en/content/Database Schema/Database Schema.md @@ -278,7 +278,7 @@ Insert --> End([Done]) **Section sources** - [2025_01_01_000003_create_ptero_audit_logs_table.php:11-40](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L40) - [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AuditLogService.php:15-83](file://Services/AuditLogService.php#L15-L83) +- [AuditLogService.php:15-83](file://Services/AuditLogService.php#L15-L82) ### Alert Configurations - Purpose: Define capacity monitoring thresholds and notification preferences per location or globally @@ -493,5 +493,5 @@ USERS ||--o{ PTERO_AUDIT_LOGS : "user_id FK" - [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) - [ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) - [ReservationService.php:335-405](file://Services/ReservationService.php#L335-L405) -- [AuditLogService.php:15-83](file://Services/AuditLogService.php#L15-L83) +- [AuditLogService.php:15-83](file://Services/AuditLogService.php#L15-L82) - [AlertService.php:77-101](file://Services/AlertService.php#L77-L101) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Database Schema/Model Relationships and Eloquent Models.md b/.qoder/repowiki/en/content/Database Schema/Model Relationships and Eloquent Models.md index 7703da2..9f74e90 100644 --- a/.qoder/repowiki/en/content/Database Schema/Model Relationships and Eloquent Models.md +++ b/.qoder/repowiki/en/content/Database Schema/Model Relationships and Eloquent Models.md @@ -73,24 +73,24 @@ M4 -.enum change.-> RR ``` **Diagram sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L66) -- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L57) -- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L34) -- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L38) -- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L70) -- [AuditLogService.php:10-83](file://Services/AuditLogService.php#L10-L83) +- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) +- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L33) +- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L37) +- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L69) +- [AuditLogService.php:10-83](file://Services/AuditLogService.php#L10-L82) - [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) - [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) - [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) - [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) **Section sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L66) -- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L57) -- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L38) -- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L34) -- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L70) -- [AuditLogService.php:10-83](file://Services/AuditLogService.php#L10-L83) +- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) +- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L56) +- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L37) +- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L33) +- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L69) +- [AuditLogService.php:10-83](file://Services/AuditLogService.php#L10-L82) - [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) - [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) - [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) @@ -109,11 +109,11 @@ Key behaviors: - AlertConfigObserver writes audit entries on create/update/delete, redacting sensitive webhook URLs before logging. **Section sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L66) -- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L57) -- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L38) -- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L34) -- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L70) +- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) +- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L56) +- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L37) +- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L33) +- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L69) ## Architecture Overview The models interact through relationships and observers to enforce business rules and maintain auditability. @@ -190,12 +190,12 @@ AuditLogService --> "AuditLog" : writes ``` **Diagram sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L66) -- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L57) -- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L34) -- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L38) -- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L70) -- [AuditLogService.php:10-83](file://Services/AuditLogService.php#L10-L83) +- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) +- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L33) +- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L37) +- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L69) +- [AuditLogService.php:10-83](file://Services/AuditLogService.php#L10-L82) ## Detailed Component Analysis @@ -228,7 +228,7 @@ Best practices: - When updating status, ensure idempotency and avoid race conditions using pessimistic locking where appropriate. **Section sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L66) +- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) - [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) - [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) - [ReservationService.php:296-330](file://Services/ReservationService.php#L296-L330) @@ -272,9 +272,9 @@ Best practices: - Ensure webhook_url is never exposed in logs or responses; rely on observer redaction. **Section sources** -- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L57) -- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L34) -- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L70) +- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L33) +- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L69) - [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) #### AlertConfig Observer Sequence @@ -324,8 +324,8 @@ Best practices: - Use getEntityHistory for UIs showing change timelines. **Section sources** -- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L38) -- [AuditLogService.php:10-83](file://Services/AuditLogService.php#L10-L83) +- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L37) +- [AuditLogService.php:10-83](file://Services/AuditLogService.php#L10-L82) - [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) ### Common Model Interactions and Best Practices diff --git a/.qoder/repowiki/en/content/Database Schema/Resource Reservations Table.md b/.qoder/repowiki/en/content/Database Schema/Resource Reservations Table.md index fe1220c..4f0de77 100644 --- a/.qoder/repowiki/en/content/Database Schema/Resource Reservations Table.md +++ b/.qoder/repowiki/en/content/Database Schema/Resource Reservations Table.md @@ -58,22 +58,22 @@ RQ --> C **Diagram sources** - [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L454) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L138) -- [AdminReservationController.php:9-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L76) -- [CartItemCreatedListener.php:11-174](file://Listeners/CartItemCreatedListener.php#L11-L174) -- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L163) -- [ResourceReservationPolicy.php:9-70](file://Policies/ResourceReservationPolicy.php#L9-L70) +- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) +- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminReservationController.php:9-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) +- [CartItemCreatedListener.php:11-174](file://Listeners/CartItemCreatedListener.php#L11-L173) +- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L162) +- [ResourceReservationPolicy.php:9-70](file://Policies/ResourceReservationPolicy.php#L9-L69) **Section sources** - [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) - [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L454) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L138) -- [AdminReservationController.php:9-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L76) -- [CartItemCreatedListener.php:11-174](file://Listeners/CartItemCreatedListener.php#L11-L174) -- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L163) -- [ResourceReservationPolicy.php:9-70](file://Policies/ResourceReservationPolicy.php#L9-L70) +- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) +- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminReservationController.php:9-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) +- [CartItemCreatedListener.php:11-174](file://Listeners/CartItemCreatedListener.php#L11-L173) +- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L162) +- [ResourceReservationPolicy.php:9-70](file://Policies/ResourceReservationPolicy.php#L9-L69) ## Core Components - Schema and constraints are defined in the initial migration and subsequent migrations that adjust status values and add idempotency support. @@ -89,12 +89,12 @@ RQ --> C - [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) - [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-31](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L31) - [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L454) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L138) -- [AdminReservationController.php:9-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L76) -- [CartItemCreatedListener.php:11-174](file://Listeners/CartItemCreatedListener.php#L11-L174) -- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L163) -- [ResourceReservationPolicy.php:9-70](file://Policies/ResourceReservationPolicy.php#L9-L70) +- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) +- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminReservationController.php:9-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) +- [CartItemCreatedListener.php:11-174](file://Listeners/CartItemCreatedListener.php#L11-L173) +- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L162) +- [ResourceReservationPolicy.php:9-70](file://Policies/ResourceReservationPolicy.php#L9-L69) ## Architecture Overview The reservation lifecycle ensures temporary resource holds until payment completes or TTL expires. Creation uses pessimistic locking to avoid overselling, and idempotency prevents duplicate reservations under concurrent requests. Status transitions are enforced at the service layer with authorization checks via policies. @@ -262,7 +262,7 @@ Authorization: - Supports idempotency_key via header or body **Section sources** -- [StoreReservationRequest.php:12-163](file://Http/Requests/StoreReservationRequest.php#L12-L163) +- [StoreReservationRequest.php:12-163](file://Http/Requests/StoreReservationRequest.php#L12-L162) ### Listener: CartItemCreatedListener - Detects products with dynamic_slider config options diff --git a/.qoder/repowiki/en/content/Getting Started.md b/.qoder/repowiki/en/content/Getting Started.md index 33b6c8e..d062585 100644 --- a/.qoder/repowiki/en/content/Getting Started.md +++ b/.qoder/repowiki/en/content/Getting Started.md @@ -181,7 +181,7 @@ Expire --> EndExpired["Released back to pool"] **Section sources** - [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) - [Services/ReservationService.php:384-405](file://Services/ReservationService.php#L384-L405) -- [Models/ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L66) +- [Models/ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) ### Relationship to Paymenter’s Built-in Pterodactyl Server Extension - This extension is a companion enhancement. It handles dynamic sliders, availability, and reservations. diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 9a8c2c4..5101eea 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -69,18 +69,18 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](file://phpunit.xml#L1-L43) - [tests/bootstrap.php:1-21](file://tests/bootstrap.php#L1-L21) -- [tests/TestCase.php:1-64](file://tests/TestCase.php#L1-L64) +- [tests/TestCase.php:1-64](file://tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](file://tests/LaravelTestCase.php#L1-L183) -- [Services/ReservationService.php:1-454](file://Services/ReservationService.php#L1-L454) +- [Services/ReservationService.php:1-454](file://Services/ReservationService.php#L1-L453) - [Services/ResourceCalculationService.php:1-545](file://Services/ResourceCalculationService.php#L1-L545) -- [Services/AlertService.php:1-393](file://Services/AlertService.php#L1-L393) -- [Models/ResourceReservation.php:1-66](file://Models/ResourceReservation.php#L1-L66) -- [Models/AlertConfig.php:1-57](file://Models/AlertConfig.php#L1-L57) +- [Services/AlertService.php:1-393](file://Services/AlertService.php#L1-L392) +- [Models/ResourceReservation.php:1-66](file://Models/ResourceReservation.php#L1-L65) +- [Models/AlertConfig.php:1-57](file://Models/AlertConfig.php#L1-L56) **Section sources** - [phpunit.xml:1-43](file://phpunit.xml#L1-L43) - [tests/bootstrap.php:1-21](file://tests/bootstrap.php#L1-L21) -- [tests/TestCase.php:1-64](file://tests/TestCase.php#L1-L64) +- [tests/TestCase.php:1-64](file://tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](file://tests/LaravelTestCase.php#L1-L183) ## Core Components @@ -91,11 +91,11 @@ Key components under test: - Models: ResourceReservation and AlertConfig define data contracts and scopes used by services. **Section sources** -- [Services/ReservationService.php:1-454](file://Services/ReservationService.php#L1-L454) +- [Services/ReservationService.php:1-454](file://Services/ReservationService.php#L1-L453) - [Services/ResourceCalculationService.php:1-545](file://Services/ResourceCalculationService.php#L1-L545) -- [Services/AlertService.php:1-393](file://Services/AlertService.php#L1-L393) -- [Models/ResourceReservation.php:1-66](file://Models/ResourceReservation.php#L1-L66) -- [Models/AlertConfig.php:1-57](file://Models/AlertConfig.php#L1-L57) +- [Services/AlertService.php:1-393](file://Services/AlertService.php#L1-L392) +- [Models/ResourceReservation.php:1-66](file://Models/ResourceReservation.php#L1-L65) +- [Models/AlertConfig.php:1-57](file://Models/AlertConfig.php#L1-L56) ## Architecture Overview The testing architecture isolates external dependencies and enforces deterministic environments: @@ -251,9 +251,9 @@ Key test patterns: - Assert AlertDeliveryFailed event dispatch when all channels fail. **Section sources** -- [tests/Unit/AlertServiceTest.php:1-771](file://tests/Unit/AlertServiceTest.php#L1-L771) +- [tests/Unit/AlertServiceTest.php:1-771](file://tests/Unit/AlertServiceTest.php#L1-L770) - [Services/AlertService.php:33-248](file://Services/AlertService.php#L33-L248) -- [Models/AlertConfig.php:1-57](file://Models/AlertConfig.php#L1-L57) +- [Models/AlertConfig.php:1-57](file://Models/AlertConfig.php#L1-L56) ### Feature Tests for API Endpoints Focus areas: @@ -291,7 +291,7 @@ Key test patterns: - Assert throttling behavior at both guest IP and user levels. **Section sources** -- [tests/Feature/ReservationApiTest.php:1-491](file://tests/Feature/ReservationApiTest.php#L1-L491) +- [tests/Feature/ReservationApiTest.php:1-491](file://tests/Feature/ReservationApiTest.php#L1-L490) - [tests/Feature/AvailabilityApiTest.php:1-95](file://tests/Feature/AvailabilityApiTest.php#L1-L95) ## Dependency Analysis From fcc3df97d133f1ce9eef8c9231626e128730210a Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 00:14:08 +1000 Subject: [PATCH 29/95] docs: align qoder anchor labels --- .../en/content/API Reference/API Reference.md | 20 +++---- .../Admin API Endpoints.md | 4 +- .../Public API Endpoints.md | 2 +- .../Reservation Endpoints.md | 16 ++--- .qoder/repowiki/en/content/Admin Interface.md | 38 ++++++------ .../Companion Extension Pattern.md | 20 +++---- .../Service Layer Design/Alert Service.md | 10 ++-- .../Node Selection Service.md | 8 +-- .../Service Layer Design.md | 18 +++--- .../Supporting Services.md | 12 ++-- .../Core Services/ConfigOptionSetupService.md | 4 +- .../ResourceCalculationService.md | 6 +- .../SliderConfigReaderService.md | 4 +- .../Database Schema/Database Schema.md | 4 +- ...Model Relationships and Eloquent Models.md | 58 +++++++++---------- .../Resource Reservations Table.md | 38 ++++++------ .qoder/repowiki/en/content/Getting Started.md | 2 +- .qoder/repowiki/en/content/Testing.md | 26 ++++----- 18 files changed, 145 insertions(+), 145 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index 8d0c7d9..b44aa9d 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -59,7 +59,7 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] - [routes/api.php:17-40](file://routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-41](file://routes/api.php#L1-L40) +- [routes/api.php:1-40](file://routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -70,10 +70,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] **Section sources** - [AvailabilityController.php:9-70](file://Http/Controllers/Api/AvailabilityController.php#L9-L70) -- [PricingController.php:12-158](file://Http/Controllers/Api/PricingController.php#L12-L157) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [AdminCapacityController.php:8-63](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) -- [AdminReservationController.php:9-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) +- [PricingController.php:12-157](file://Http/Controllers/Api/PricingController.php#L12-L157) +- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminCapacityController.php:8-62](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) +- [AdminReservationController.php:9-75](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) ## Architecture Overview The API integrates with Paymenter core models and services and with the Pterodactyl panel via HTTP. Services encapsulate business logic and data aggregation. @@ -204,7 +204,7 @@ Important: **Section sources** - [routes/api.php:17-22](file://routes/api.php#L17-L22) -- [PricingController.php:24-158](file://Http/Controllers/Api/PricingController.php#L24-L157) +- [PricingController.php:24-157](file://Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](file://Http/Requests/StoreReservationRequest.php#L38-L112) #### Reservations @@ -288,8 +288,8 @@ Notes: **Section sources** - [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:24-138](file://Http/Controllers/Api/ReservationController.php#L24-L137) -- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L162) +- [ReservationController.php:24-137](file://Http/Controllers/Api/ReservationController.php#L24-L137) +- [StoreReservationRequest.php:10-162](file://Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) - [ResourceReservationPolicy.php:25-58](file://Policies/ResourceReservationPolicy.php#L25-L58) @@ -318,7 +318,7 @@ Notes: **Section sources** - [routes/api.php:32-40](file://routes/api.php#L32-L40) -- [AdminCapacityController.php:17-63](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) +- [AdminCapacityController.php:17-62](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) #### Admin Reservations @@ -353,7 +353,7 @@ Notes: **Section sources** - [routes/api.php:32-40](file://routes/api.php#L32-L40) -- [AdminReservationController.php:18-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) +- [AdminReservationController.php:18-75](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) ## Dependency Analysis diff --git a/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md b/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md index b356ffd..4581b92 100644 --- a/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md @@ -349,10 +349,10 @@ RESOURCE_RESERVATION ||--o| SERVICE : "service_id" ``` **Diagram sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) +- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) **Section sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) +- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) ## Dependency Analysis - Admin controllers depend on services: diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md index 4a1f07c..6d8b5f5 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md @@ -80,7 +80,7 @@ ResSvc --> DB["Database (ptero_resource_reservations)"] - [Http/Controllers/Api/ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) - [Http/Requests/StoreReservationRequest.php:38-113](file://Http/Requests/StoreReservationRequest.php#L38-L113) - [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Models/ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) +- [Models/ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) - [Policies/ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) ## Architecture Overview diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Reservation Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Reservation Endpoints.md index 708ceb5..31faf8d 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Reservation Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Reservation Endpoints.md @@ -48,8 +48,8 @@ Controller --> Policy["ResourceReservationPolicy"] **Diagram sources** - [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [ReservationService.php:43-454](file://Services/ReservationService.php#L43-L453) +- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [ReservationService.php:43-453](file://Services/ReservationService.php#L43-L453) - [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) **Section sources** @@ -73,7 +73,7 @@ Key responsibilities: - [routes/api.php:24-30](file://routes/api.php#L24-L30) - [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) - [StoreReservationRequest.php:31-113](file://Http/Requests/StoreReservationRequest.php#L31-L113) -- [ReservationService.php:43-454](file://Services/ReservationService.php#L43-L453) +- [ReservationService.php:43-453](file://Services/ReservationService.php#L43-L453) - [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) - [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) @@ -380,15 +380,15 @@ Service --> DB["Database"] **Diagram sources** - [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L162) +- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [StoreReservationRequest.php:10-162](file://Http/Requests/StoreReservationRequest.php#L10-L162) - [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) +- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) **Section sources** - [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) +- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) ## Performance Considerations - Pessimistic locking: Uses lockForUpdate to prevent concurrent modifications during node selection and reservation creation. diff --git a/.qoder/repowiki/en/content/Admin Interface.md b/.qoder/repowiki/en/content/Admin Interface.md index 945ee2a..b8509f2 100644 --- a/.qoder/repowiki/en/content/Admin Interface.md +++ b/.qoder/repowiki/en/content/Admin Interface.md @@ -89,10 +89,10 @@ AL --> ALS - [AuditLogPage.php:15-29](file://Admin/Pages/AuditLogPage.php#L15-L29) - [ReservationResource.php:15-27](file://Admin/Resources/ReservationResource.php#L15-L27) - [AlertConfigResource.php:27-39](file://Admin/Resources/AlertConfigResource.php#L27-L39) -- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L103) -- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L109) -- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L5) -- [audit-log.blade.php:1-48](file://resources/views/admin/audit-log.blade.php#L1-L47) +- [dashboard.blade.php:1-103](file://resources/views/admin/dashboard.blade.php#L1-L103) +- [node-monitoring.blade.php:1-109](file://resources/views/admin/node-monitoring.blade.php#L1-L109) +- [setup-wizard.blade.php:1-5](file://resources/views/admin/setup-wizard.blade.php#L1-L5) +- [audit-log.blade.php:1-47](file://resources/views/admin/audit-log.blade.php#L1-L47) - [ResourceCalculationService.php:10-22](file://Services/ResourceCalculationService.php#L10-L22) - [ReservationService.php:16-35](file://Services/ReservationService.php#L16-L35) - [AuditLogService.php:10-41](file://Services/AuditLogService.php#L10-L41) @@ -115,13 +115,13 @@ AL --> ALS **Section sources** - [Dashboard.php:27-73](file://Admin/Pages/Dashboard.php#L27-L73) -- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L103) +- [dashboard.blade.php:1-103](file://resources/views/admin/dashboard.blade.php#L1-L103) - [NodeMonitoring.php:22-61](file://Admin/Pages/NodeMonitoring.php#L22-L61) -- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L109) +- [node-monitoring.blade.php:1-109](file://resources/views/admin/node-monitoring.blade.php#L1-L109) - [SetupWizard.php:50-427](file://Admin/Pages/SetupWizard.php#L50-L427) -- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L5) +- [setup-wizard.blade.php:1-5](file://resources/views/admin/setup-wizard.blade.php#L1-L5) - [AuditLogPage.php:31-103](file://Admin/Pages/AuditLogPage.php#L31-L103) -- [audit-log.blade.php:1-48](file://resources/views/admin/audit-log.blade.php#L1-L47) +- [audit-log.blade.php:1-47](file://resources/views/admin/audit-log.blade.php#L1-L47) - [ReservationResource.php:34-127](file://Admin/Resources/ReservationResource.php#L34-L127) - [AlertConfigResource.php:41-176](file://Admin/Resources/AlertConfigResource.php#L41-L176) @@ -176,12 +176,12 @@ ShowErr --> Render **Diagram sources** - [Dashboard.php:27-73](file://Admin/Pages/Dashboard.php#L27-L73) -- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L103) +- [dashboard.blade.php:1-103](file://resources/views/admin/dashboard.blade.php#L1-L103) - [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) **Section sources** - [Dashboard.php:27-115](file://Admin/Pages/Dashboard.php#L27-L115) -- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L103) +- [dashboard.blade.php:1-103](file://resources/views/admin/dashboard.blade.php#L1-L103) ### Node Monitoring - Purpose: Real-time view of node utilization and availability per location. @@ -208,11 +208,11 @@ NM-->>Admin : Render table with utilization **Diagram sources** - [NodeMonitoring.php:22-61](file://Admin/Pages/NodeMonitoring.php#L22-L61) - [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L109) +- [node-monitoring.blade.php:1-109](file://resources/views/admin/node-monitoring.blade.php#L1-L109) **Section sources** - [NodeMonitoring.php:22-61](file://Admin/Pages/NodeMonitoring.php#L22-L61) -- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L109) +- [node-monitoring.blade.php:1-109](file://resources/views/admin/node-monitoring.blade.php#L1-L109) ### Setup Wizard - Purpose: Configure dynamic slider options for a selected product, including pricing models and allowed locations. @@ -239,11 +239,11 @@ G --> |Yes| I["Success Notification & Reset Form"] **Diagram sources** - [SetupWizard.php:50-427](file://Admin/Pages/SetupWizard.php#L50-L427) -- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L5) +- [setup-wizard.blade.php:1-5](file://resources/views/admin/setup-wizard.blade.php#L1-L5) **Section sources** - [SetupWizard.php:50-509](file://Admin/Pages/SetupWizard.php#L50-L509) -- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L5) +- [setup-wizard.blade.php:1-5](file://resources/views/admin/setup-wizard.blade.php#L1-L5) ### Audit Log Viewer - Purpose: Track administrative actions and display recent alert delivery failures. @@ -274,7 +274,7 @@ AuditLogPage --> AuditLog : "queries" **Section sources** - [AuditLogPage.php:31-103](file://Admin/Pages/AuditLogPage.php#L31-L103) -- [audit-log.blade.php:1-48](file://resources/views/admin/audit-log.blade.php#L1-L47) +- [audit-log.blade.php:1-47](file://resources/views/admin/audit-log.blade.php#L1-L47) ### Reservation Management Resource - Purpose: Manual intervention for pending reservations (extend TTL, cancel) and bulk cleanup of expired ones. @@ -433,10 +433,10 @@ The Filament 4 admin interface provides a comprehensive operational view of syst - Extensibility: Add custom columns, filters, or actions in resources; customize views with standard Blade patterns. **Section sources** -- [dashboard.blade.php:1-104](file://resources/views/admin/dashboard.blade.php#L1-L103) -- [node-monitoring.blade.php:1-110](file://resources/views/admin/node-monitoring.blade.php#L1-L109) -- [setup-wizard.blade.php:1-6](file://resources/views/admin/setup-wizard.blade.php#L1-L5) -- [audit-log.blade.php:1-48](file://resources/views/admin/audit-log.blade.php#L1-L47) +- [dashboard.blade.php:1-103](file://resources/views/admin/dashboard.blade.php#L1-L103) +- [node-monitoring.blade.php:1-109](file://resources/views/admin/node-monitoring.blade.php#L1-L109) +- [setup-wizard.blade.php:1-5](file://resources/views/admin/setup-wizard.blade.php#L1-L5) +- [audit-log.blade.php:1-47](file://resources/views/admin/audit-log.blade.php#L1-L47) ### Integration Points - Pterodactyl API: diff --git a/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md b/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md index 2decfce..726cf6e 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md @@ -84,12 +84,12 @@ G --> M["Admin Recipients"] **Section sources** - [DynamicPterodactyl.php:48-127](file://DynamicPterodactyl.php#L48-L127) -- [Services/ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) +- [Services/ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) - [Services/ResourceCalculationService.php:10-545](file://Services/ResourceCalculationService.php#L10-L545) -- [Services/AlertService.php:19-393](file://Services/AlertService.php#L19-L392) -- [Services/SliderConfigReaderService.php:7-69](file://Services/SliderConfigReaderService.php#L7-L68) -- [Listeners/CartItemCreatedListener.php:11-174](file://Listeners/CartItemCreatedListener.php#L11-L173) -- [Listeners/InvoicePaidListener.php:12-136](file://Listeners/InvoicePaidListener.php#L12-L135) +- [Services/AlertService.php:19-392](file://Services/AlertService.php#L19-L392) +- [Services/SliderConfigReaderService.php:7-68](file://Services/SliderConfigReaderService.php#L7-L68) +- [Listeners/CartItemCreatedListener.php:11-173](file://Listeners/CartItemCreatedListener.php#L11-L173) +- [Listeners/InvoicePaidListener.php:12-135](file://Listeners/InvoicePaidListener.php#L12-L135) ## Architecture Overview The extension follows a companion pattern: @@ -245,11 +245,11 @@ IPay->>IPay : notifyShortfall on failure **Diagram sources** - [Listeners/CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [Listeners/InvoicePaidListener.php:14-136](file://Listeners/InvoicePaidListener.php#L14-L135) +- [Listeners/InvoicePaidListener.php:14-135](file://Listeners/InvoicePaidListener.php#L14-L135) **Section sources** -- [Listeners/CartItemCreatedListener.php:13-174](file://Listeners/CartItemCreatedListener.php#L13-L173) -- [Listeners/InvoicePaidListener.php:14-136](file://Listeners/InvoicePaidListener.php#L14-L135) +- [Listeners/CartItemCreatedListener.php:13-173](file://Listeners/CartItemCreatedListener.php#L13-L173) +- [Listeners/InvoicePaidListener.php:14-135](file://Listeners/InvoicePaidListener.php#L14-L135) ### Pricing Coexistence: Native Slider Metadata Only - SliderConfigReaderService reads dynamic_slider ConfigOption metadata (min, max, step, default, unit, display_unit, display_divisor, pricing model/rates) for frontend consumption. @@ -270,7 +270,7 @@ SliderConfigReaderService --> ConfigOption : "reads metadata" ``` **Diagram sources** -- [Services/SliderConfigReaderService.php:7-69](file://Services/SliderConfigReaderService.php#L7-L68) +- [Services/SliderConfigReaderService.php:7-68](file://Services/SliderConfigReaderService.php#L7-L68) **Section sources** - [Services/SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) @@ -353,7 +353,7 @@ Common issues and diagnostics: - Alert delivery failures: check AlertService sendNotifications and delivery logs; ensure email/webhook channels are configured and recipients exist. **Section sources** -- [Listeners/InvoicePaidListener.php:58-136](file://Listeners/InvoicePaidListener.php#L58-L135) +- [Listeners/InvoicePaidListener.php:58-135](file://Listeners/InvoicePaidListener.php#L58-L135) - [Services/ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) - [Services/ReservationService.php:125-141](file://Services/ReservationService.php#L125-L141) - [Services/AlertService.php:128-248](file://Services/AlertService.php#L128-L248) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Alert Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Alert Service.md index deadc8d..151fcc5 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Alert Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Alert Service.md @@ -75,14 +75,14 @@ AlertSvc --> Event["AlertDeliveryFailed event"] - Admin AlertConfigResource: Filament resource exposing CRUD and a “Test” action to send a sample alert. **Section sources** -- [AlertService.php:19-393](file://Services/AlertService.php#L19-L392) +- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) - [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) - [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) - [CapacityAlertNotification.php:10-47](file://Notifications/CapacityAlertNotification.php#L10-L47) - [ReservationShortfallNotification.php:10-40](file://Notifications/ReservationShortfallNotification.php#L10-L40) - [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) - [AlertConfigObserver.php:8-69](file://Models/Observers/AlertConfigObserver.php#L8-L69) -- [AlertConfigResource.php:150-197](file://Admin/Resources/AlertConfigResource.php#L150-L196) +- [AlertConfigResource.php:150-196](file://Admin/Resources/AlertConfigResource.php#L150-L196) ## Architecture Overview The service is invoked by a scheduled task registered during extension boot. For each active alert configuration, it determines the scope (global or specific location), fetches current availability from Pterodactyl via ResourceCalculationService, evaluates memory and disk utilization against configured warning/critical thresholds, and dispatches notifications if any thresholds are breached. Cooldown prevents repeated alerts within a configured window. Delivery attempts are recorded, and failures emit an event for downstream handling. @@ -216,7 +216,7 @@ Migration highlights: **Section sources** - [DynamicPterodactyl.php:118-126](file://DynamicPterodactyl.php#L118-L126) -- [AlertConfigResource.php:150-197](file://Admin/Resources/AlertConfigResource.php#L150-L196) +- [AlertConfigResource.php:150-196](file://Admin/Resources/AlertConfigResource.php#L150-L196) - [AlertConfigObserver.php:12-69](file://Models/Observers/AlertConfigObserver.php#L12-L69) ## Dependency Analysis @@ -261,7 +261,7 @@ AlertService --> AlertDeliveryFailed : "dispatches on failure" ``` **Diagram sources** -- [AlertService.php:19-393](file://Services/AlertService.php#L19-L392) +- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) - [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) - [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) - [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) @@ -270,7 +270,7 @@ AlertService --> AlertDeliveryFailed : "dispatches on failure" - [AlertDeliveryFailed.php:9-16](file://Events/AlertDeliveryFailed.php#L9-L16) **Section sources** -- [AlertService.php:19-393](file://Services/AlertService.php#L19-L392) +- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) - [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) ## Performance Considerations diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md index 44eb7bd..c843445 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md @@ -50,8 +50,8 @@ RCSvc --> DB **Section sources** - [NodeSelectionService.php:1-88](file://Services/NodeSelectionService.php#L1-L88) - [ResourceCalculationService.php:1-545](file://Services/ResourceCalculationService.php#L1-L545) -- [ReservationService.php:1-454](file://Services/ReservationService.php#L1-L453) -- [ResourceReservation.php:1-66](file://Models/ResourceReservation.php#L1-L65) +- [ReservationService.php:1-453](file://Services/ReservationService.php#L1-L453) +- [ResourceReservation.php:1-65](file://Models/ResourceReservation.php#L1-L65) ## Core Components - NodeSelectionService: Selects the best node using weighted headroom scoring and filters out unsuitable nodes (maintenance mode or insufficient resources). @@ -257,11 +257,11 @@ Pending --> Cancelled : "cancel(token)" ``` **Diagram sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) +- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) - [2026_04_22_000001_drop_released_from_reservation_status.php:8-19](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L19) **Section sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) +- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) - [2026_04_22_000001_drop_released_from_reservation_status.php:8-19](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L19) ## Dependency Analysis diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md index dc14f03..d4bdb90 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md @@ -72,11 +72,11 @@ ResCalcSvc --> DB **Section sources** - [ResourceCalculationService.php:10-222](file://Services/ResourceCalculationService.php#L10-L222) - [NodeSelectionService.php:5-86](file://Services/NodeSelectionService.php#L5-L86) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) -- [AlertService.php:19-393](file://Services/AlertService.php#L19-L392) +- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) +- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) - [AvailabilityController.php:9-71](file://Http/Controllers/Api/AvailabilityController.php#L9-L71) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [AdminCapacityController.php:8-63](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) +- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminCapacityController.php:8-62](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) ## Architecture Overview The service layer enforces strict boundaries: @@ -226,7 +226,7 @@ end **Section sources** - [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) - [ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) -- [ReservationService.php:387-454](file://Services/ReservationService.php#L387-L453) +- [ReservationService.php:387-453](file://Services/ReservationService.php#L387-L453) ### AlertService Responsibilities: @@ -300,11 +300,11 @@ AdminCapacityController --> ResourceCalculationService : "uses" **Diagram sources** - [NodeSelectionService.php:5-86](file://Services/NodeSelectionService.php#L5-L86) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) -- [AlertService.php:19-393](file://Services/AlertService.php#L19-L392) +- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) +- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) - [AvailabilityController.php:9-71](file://Http/Controllers/Api/AvailabilityController.php#L9-L71) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [AdminCapacityController.php:8-63](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) +- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminCapacityController.php:8-62](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) **Section sources** - [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Supporting Services.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Supporting Services.md index d0a0c2c..7c1bd63 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Supporting Services.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Supporting Services.md @@ -72,12 +72,12 @@ A --> I - [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) **Section sources** -- [AuditLogService.php:1-83](file://Services/AuditLogService.php#L1-L82) -- [ConfigOptionSetupService.php:1-260](file://Services/ConfigOptionSetupService.php#L1-L259) -- [SliderConfigReaderService.php:1-69](file://Services/SliderConfigReaderService.php#L1-L68) -- [PricingController.php:1-158](file://Http/Controllers/Api/PricingController.php#L1-L157) -- [AuditLogPage.php:1-105](file://Admin/Pages/AuditLogPage.php#L1-L104) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:1-55](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L1-L54) +- [AuditLogService.php:1-82](file://Services/AuditLogService.php#L1-L82) +- [ConfigOptionSetupService.php:1-259](file://Services/ConfigOptionSetupService.php#L1-L259) +- [SliderConfigReaderService.php:1-68](file://Services/SliderConfigReaderService.php#L1-L68) +- [PricingController.php:1-157](file://Http/Controllers/Api/PricingController.php#L1-L157) +- [AuditLogPage.php:1-104](file://Admin/Pages/AuditLogPage.php#L1-L104) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:1-54](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L1-L54) ## Core Components - AuditLogService: Provides methods to log actions and retrieve filtered logs. Captures user context, request metadata, and before/after values for changes. diff --git a/.qoder/repowiki/en/content/Core Services/ConfigOptionSetupService.md b/.qoder/repowiki/en/content/Core Services/ConfigOptionSetupService.md index f13a6ee..0505482 100644 --- a/.qoder/repowiki/en/content/Core Services/ConfigOptionSetupService.md +++ b/.qoder/repowiki/en/content/Core Services/ConfigOptionSetupService.md @@ -50,8 +50,8 @@ H["StoreReservationRequest"] --> C - [StoreReservationRequest.php:75-140](file://Http/Requests/StoreReservationRequest.php#L75-L140) **Section sources** -- [ConfigOptionSetupService.php:1-260](file://Services/ConfigOptionSetupService.php#L1-L259) -- [SliderConfigReaderService.php:1-69](file://Services/SliderConfigReaderService.php#L1-L68) +- [ConfigOptionSetupService.php:1-259](file://Services/ConfigOptionSetupService.php#L1-L259) +- [SliderConfigReaderService.php:1-68](file://Services/SliderConfigReaderService.php#L1-L68) ## Core Components - ConfigOptionSetupService: Creates/updates dynamic_slider ConfigOptions for memory, CPU, disk, and optionally Location; validates pricing metadata; audits setup runs. diff --git a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md index 4a01018..dbe54de 100644 --- a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md +++ b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md @@ -76,7 +76,7 @@ Responsibilities summary: - [ResourceCalculationService.php:26-222](file://Services/ResourceCalculationService.php#L26-L222) - [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) - [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) +- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) ## Architecture Overview The service uses a thin HTTP client wrapper around Pterodactyl’s Application API with retries on transient connection errors, strict timeouts, and sanitized error propagation. For cluster-wide snapshots, it batches node and server data retrieval to reduce API calls while preserving accuracy. @@ -286,9 +286,9 @@ ResourceCalculationService --> ResourceReservation : "reads pending" **Diagram sources** - [ResourceCalculationService.php:10-545](file://Services/ResourceCalculationService.php#L10-L545) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) +- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) - [NodeSelectionService.php:5-88](file://Services/NodeSelectionService.php#L5-L88) -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) +- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) ## Dependency Analysis - External dependency: Pterodactyl Application API via HTTP client diff --git a/.qoder/repowiki/en/content/Core Services/SliderConfigReaderService.md b/.qoder/repowiki/en/content/Core Services/SliderConfigReaderService.md index e4e0f43..9674e5a 100644 --- a/.qoder/repowiki/en/content/Core Services/SliderConfigReaderService.md +++ b/.qoder/repowiki/en/content/Core Services/SliderConfigReaderService.md @@ -239,7 +239,7 @@ ConfigOptionSetupService --> ConfigOption : "creates/updates" **Section sources** - [ConfigOptionSetupService.php:117-171](file://Services/ConfigOptionSetupService.php#L117-L171) - [07-PRICING-MODELS.md:31-53](file://07-PRICING-MODELS.md#L31-L53) -- [07-PRICING-MODELS.md:290-330](file://07-PRICING-MODELS.md#L290-L329) +- [07-PRICING-MODELS.md:290-329](file://07-PRICING-MODELS.md#L290-L329) ### Example Slider Configuration Structures Typical structures produced by the service for frontend consumption: @@ -377,4 +377,4 @@ SliderConfigReaderService provides a clean, read-only interface to dynamic slide **Section sources** - [PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) -- [07-PRICING-MODELS.md:290-330](file://07-PRICING-MODELS.md#L290-L329) \ No newline at end of file +- [07-PRICING-MODELS.md:290-329](file://07-PRICING-MODELS.md#L290-L329) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Database Schema/Database Schema.md b/.qoder/repowiki/en/content/Database Schema/Database Schema.md index b8c83b4..633270c 100644 --- a/.qoder/repowiki/en/content/Database Schema/Database Schema.md +++ b/.qoder/repowiki/en/content/Database Schema/Database Schema.md @@ -278,7 +278,7 @@ Insert --> End([Done]) **Section sources** - [2025_01_01_000003_create_ptero_audit_logs_table.php:11-40](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L40) - [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AuditLogService.php:15-83](file://Services/AuditLogService.php#L15-L82) +- [AuditLogService.php:15-82](file://Services/AuditLogService.php#L15-L82) ### Alert Configurations - Purpose: Define capacity monitoring thresholds and notification preferences per location or globally @@ -493,5 +493,5 @@ USERS ||--o{ PTERO_AUDIT_LOGS : "user_id FK" - [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) - [ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) - [ReservationService.php:335-405](file://Services/ReservationService.php#L335-L405) -- [AuditLogService.php:15-83](file://Services/AuditLogService.php#L15-L82) +- [AuditLogService.php:15-82](file://Services/AuditLogService.php#L15-L82) - [AlertService.php:77-101](file://Services/AlertService.php#L77-L101) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Database Schema/Model Relationships and Eloquent Models.md b/.qoder/repowiki/en/content/Database Schema/Model Relationships and Eloquent Models.md index 9f74e90..6e8332b 100644 --- a/.qoder/repowiki/en/content/Database Schema/Model Relationships and Eloquent Models.md +++ b/.qoder/repowiki/en/content/Database Schema/Model Relationships and Eloquent Models.md @@ -73,24 +73,24 @@ M4 -.enum change.-> RR ``` **Diagram sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) -- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L56) -- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L33) -- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L37) -- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L69) -- [AuditLogService.php:10-83](file://Services/AuditLogService.php#L10-L82) +- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) +- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) +- [AlertConfigObserver.php:8-69](file://Models/Observers/AlertConfigObserver.php#L8-L69) +- [AuditLogService.php:10-82](file://Services/AuditLogService.php#L10-L82) - [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) - [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) - [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) - [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) **Section sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) -- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L56) -- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L37) -- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L33) -- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L69) -- [AuditLogService.php:10-83](file://Services/AuditLogService.php#L10-L82) +- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) +- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) +- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) +- [AlertConfigObserver.php:8-69](file://Models/Observers/AlertConfigObserver.php#L8-L69) +- [AuditLogService.php:10-82](file://Services/AuditLogService.php#L10-L82) - [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) - [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) - [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) @@ -109,11 +109,11 @@ Key behaviors: - AlertConfigObserver writes audit entries on create/update/delete, redacting sensitive webhook URLs before logging. **Section sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) -- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L56) -- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L37) -- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L33) -- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L69) +- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) +- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) +- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) +- [AlertConfigObserver.php:8-69](file://Models/Observers/AlertConfigObserver.php#L8-L69) ## Architecture Overview The models interact through relationships and observers to enforce business rules and maintain auditability. @@ -190,12 +190,12 @@ AuditLogService --> "AuditLog" : writes ``` **Diagram sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) -- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L56) -- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L33) -- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L37) -- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L69) -- [AuditLogService.php:10-83](file://Services/AuditLogService.php#L10-L82) +- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) +- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) +- [AlertConfigObserver.php:8-69](file://Models/Observers/AlertConfigObserver.php#L8-L69) +- [AuditLogService.php:10-82](file://Services/AuditLogService.php#L10-L82) ## Detailed Component Analysis @@ -228,7 +228,7 @@ Best practices: - When updating status, ensure idempotency and avoid race conditions using pessimistic locking where appropriate. **Section sources** -- [ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) +- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) - [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) - [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) - [ReservationService.php:296-330](file://Services/ReservationService.php#L296-L330) @@ -272,9 +272,9 @@ Best practices: - Ensure webhook_url is never exposed in logs or responses; rely on observer redaction. **Section sources** -- [AlertConfig.php:8-57](file://Models/AlertConfig.php#L8-L56) -- [AlertDeliveryLog.php:8-34](file://Models/AlertDeliveryLog.php#L8-L33) -- [AlertConfigObserver.php:8-70](file://Models/Observers/AlertConfigObserver.php#L8-L69) +- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) +- [AlertConfigObserver.php:8-69](file://Models/Observers/AlertConfigObserver.php#L8-L69) - [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) #### AlertConfig Observer Sequence @@ -324,8 +324,8 @@ Best practices: - Use getEntityHistory for UIs showing change timelines. **Section sources** -- [AuditLog.php:7-38](file://Models/AuditLog.php#L7-L37) -- [AuditLogService.php:10-83](file://Services/AuditLogService.php#L10-L82) +- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) +- [AuditLogService.php:10-82](file://Services/AuditLogService.php#L10-L82) - [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) ### Common Model Interactions and Best Practices diff --git a/.qoder/repowiki/en/content/Database Schema/Resource Reservations Table.md b/.qoder/repowiki/en/content/Database Schema/Resource Reservations Table.md index 4f0de77..cbadded 100644 --- a/.qoder/repowiki/en/content/Database Schema/Resource Reservations Table.md +++ b/.qoder/repowiki/en/content/Database Schema/Resource Reservations Table.md @@ -58,22 +58,22 @@ RQ --> C **Diagram sources** - [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [AdminReservationController.php:9-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) -- [CartItemCreatedListener.php:11-174](file://Listeners/CartItemCreatedListener.php#L11-L173) -- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L162) -- [ResourceReservationPolicy.php:9-70](file://Policies/ResourceReservationPolicy.php#L9-L69) +- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) +- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminReservationController.php:9-75](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) +- [CartItemCreatedListener.php:11-173](file://Listeners/CartItemCreatedListener.php#L11-L173) +- [StoreReservationRequest.php:10-162](file://Http/Requests/StoreReservationRequest.php#L10-L162) +- [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) **Section sources** - [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) - [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [AdminReservationController.php:9-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) -- [CartItemCreatedListener.php:11-174](file://Listeners/CartItemCreatedListener.php#L11-L173) -- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L162) -- [ResourceReservationPolicy.php:9-70](file://Policies/ResourceReservationPolicy.php#L9-L69) +- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) +- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminReservationController.php:9-75](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) +- [CartItemCreatedListener.php:11-173](file://Listeners/CartItemCreatedListener.php#L11-L173) +- [StoreReservationRequest.php:10-162](file://Http/Requests/StoreReservationRequest.php#L10-L162) +- [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) ## Core Components - Schema and constraints are defined in the initial migration and subsequent migrations that adjust status values and add idempotency support. @@ -89,12 +89,12 @@ RQ --> C - [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) - [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-31](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L31) - [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [ReservationService.php:16-454](file://Services/ReservationService.php#L16-L453) -- [ReservationController.php:13-138](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [AdminReservationController.php:9-76](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) -- [CartItemCreatedListener.php:11-174](file://Listeners/CartItemCreatedListener.php#L11-L173) -- [StoreReservationRequest.php:10-163](file://Http/Requests/StoreReservationRequest.php#L10-L162) -- [ResourceReservationPolicy.php:9-70](file://Policies/ResourceReservationPolicy.php#L9-L69) +- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) +- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminReservationController.php:9-75](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) +- [CartItemCreatedListener.php:11-173](file://Listeners/CartItemCreatedListener.php#L11-L173) +- [StoreReservationRequest.php:10-162](file://Http/Requests/StoreReservationRequest.php#L10-L162) +- [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) ## Architecture Overview The reservation lifecycle ensures temporary resource holds until payment completes or TTL expires. Creation uses pessimistic locking to avoid overselling, and idempotency prevents duplicate reservations under concurrent requests. Status transitions are enforced at the service layer with authorization checks via policies. @@ -262,7 +262,7 @@ Authorization: - Supports idempotency_key via header or body **Section sources** -- [StoreReservationRequest.php:12-163](file://Http/Requests/StoreReservationRequest.php#L12-L162) +- [StoreReservationRequest.php:12-162](file://Http/Requests/StoreReservationRequest.php#L12-L162) ### Listener: CartItemCreatedListener - Detects products with dynamic_slider config options diff --git a/.qoder/repowiki/en/content/Getting Started.md b/.qoder/repowiki/en/content/Getting Started.md index d062585..05f33c0 100644 --- a/.qoder/repowiki/en/content/Getting Started.md +++ b/.qoder/repowiki/en/content/Getting Started.md @@ -181,7 +181,7 @@ Expire --> EndExpired["Released back to pool"] **Section sources** - [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) - [Services/ReservationService.php:384-405](file://Services/ReservationService.php#L384-L405) -- [Models/ResourceReservation.php:10-66](file://Models/ResourceReservation.php#L10-L65) +- [Models/ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) ### Relationship to Paymenter’s Built-in Pterodactyl Server Extension - This extension is a companion enhancement. It handles dynamic sliders, availability, and reservations. diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 5101eea..0ae8a56 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -69,18 +69,18 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](file://phpunit.xml#L1-L43) - [tests/bootstrap.php:1-21](file://tests/bootstrap.php#L1-L21) -- [tests/TestCase.php:1-64](file://tests/TestCase.php#L1-L63) +- [tests/TestCase.php:1-63](file://tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](file://tests/LaravelTestCase.php#L1-L183) -- [Services/ReservationService.php:1-454](file://Services/ReservationService.php#L1-L453) +- [Services/ReservationService.php:1-453](file://Services/ReservationService.php#L1-L453) - [Services/ResourceCalculationService.php:1-545](file://Services/ResourceCalculationService.php#L1-L545) -- [Services/AlertService.php:1-393](file://Services/AlertService.php#L1-L392) -- [Models/ResourceReservation.php:1-66](file://Models/ResourceReservation.php#L1-L65) -- [Models/AlertConfig.php:1-57](file://Models/AlertConfig.php#L1-L56) +- [Services/AlertService.php:1-392](file://Services/AlertService.php#L1-L392) +- [Models/ResourceReservation.php:1-65](file://Models/ResourceReservation.php#L1-L65) +- [Models/AlertConfig.php:1-56](file://Models/AlertConfig.php#L1-L56) **Section sources** - [phpunit.xml:1-43](file://phpunit.xml#L1-L43) - [tests/bootstrap.php:1-21](file://tests/bootstrap.php#L1-L21) -- [tests/TestCase.php:1-64](file://tests/TestCase.php#L1-L63) +- [tests/TestCase.php:1-63](file://tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](file://tests/LaravelTestCase.php#L1-L183) ## Core Components @@ -91,11 +91,11 @@ Key components under test: - Models: ResourceReservation and AlertConfig define data contracts and scopes used by services. **Section sources** -- [Services/ReservationService.php:1-454](file://Services/ReservationService.php#L1-L453) +- [Services/ReservationService.php:1-453](file://Services/ReservationService.php#L1-L453) - [Services/ResourceCalculationService.php:1-545](file://Services/ResourceCalculationService.php#L1-L545) -- [Services/AlertService.php:1-393](file://Services/AlertService.php#L1-L392) -- [Models/ResourceReservation.php:1-66](file://Models/ResourceReservation.php#L1-L65) -- [Models/AlertConfig.php:1-57](file://Models/AlertConfig.php#L1-L56) +- [Services/AlertService.php:1-392](file://Services/AlertService.php#L1-L392) +- [Models/ResourceReservation.php:1-65](file://Models/ResourceReservation.php#L1-L65) +- [Models/AlertConfig.php:1-56](file://Models/AlertConfig.php#L1-L56) ## Architecture Overview The testing architecture isolates external dependencies and enforces deterministic environments: @@ -251,9 +251,9 @@ Key test patterns: - Assert AlertDeliveryFailed event dispatch when all channels fail. **Section sources** -- [tests/Unit/AlertServiceTest.php:1-771](file://tests/Unit/AlertServiceTest.php#L1-L770) +- [tests/Unit/AlertServiceTest.php:1-770](file://tests/Unit/AlertServiceTest.php#L1-L770) - [Services/AlertService.php:33-248](file://Services/AlertService.php#L33-L248) -- [Models/AlertConfig.php:1-57](file://Models/AlertConfig.php#L1-L56) +- [Models/AlertConfig.php:1-56](file://Models/AlertConfig.php#L1-L56) ### Feature Tests for API Endpoints Focus areas: @@ -291,7 +291,7 @@ Key test patterns: - Assert throttling behavior at both guest IP and user levels. **Section sources** -- [tests/Feature/ReservationApiTest.php:1-491](file://tests/Feature/ReservationApiTest.php#L1-L490) +- [tests/Feature/ReservationApiTest.php:1-490](file://tests/Feature/ReservationApiTest.php#L1-L490) - [tests/Feature/AvailabilityApiTest.php:1-95](file://tests/Feature/AvailabilityApiTest.php#L1-L95) ## Dependency Analysis From a9e5b25e257b812ddd74446c610cf689bd0ea69b Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 00:32:56 +1000 Subject: [PATCH 30/95] docs: normalize qoder whitespace --- .qoder/repowiki/en/content/Testing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 0ae8a56..2247f18 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -111,7 +111,7 @@ sequenceDiagram participant L as "LaravelTestCase" participant S as "Service Under Test" participant E as "External System" - + T->>B: "Load bootstrap" B-->>T: "Guard DB name; require base classes" T->>L: "createApplication()" From 2f62b3b69c2b9159ce5cacd97b659ec8d0953bce Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 01:45:42 +1000 Subject: [PATCH 31/95] fix(reservations): enforce server-owned provisioning lifecycle --- 01-DATABASE.md | 599 +---------- 02-SERVICES.md | 928 +---------------- 03-API.md | 735 +------------ 04-EVENTS.md | 416 +------- 06-FRONTEND.md | 51 +- 08-ALGORITHMS.md | 376 +------ 09-IMPLEMENTATION.md | 363 ++----- AGENTS.md | 32 +- Admin/AGENTS.md | 6 +- Admin/Pages/Dashboard.php | 4 +- Admin/Pages/NodeMonitoring.php | 2 +- CHANGELOG.md | 11 + DECISIONS.md | 30 + DynamicPterodactyl.php | 20 +- .../Api/Admin/AdminCapacityController.php | 2 +- .../Api/AvailabilityController.php | 5 +- .../Controllers/Api/ReservationController.php | 137 --- Http/Requests/StoreReservationRequest.php | 162 --- Listeners/CartItemCreatedListener.php | 172 +--- Listeners/CartItemDeletedListener.php | 51 +- Listeners/InvoicePaidListener.php | 135 --- Listeners/ServiceCreatedListener.php | 32 - Models/ResourceReservation.php | 18 + README.md | 194 +--- Services/ConfigOptionSetupService.php | 6 +- Services/NodeSelectionService.php | 33 +- Services/ReservationConfigurationService.php | 400 ++++++++ Services/ReservationService.php | 701 ++++++++----- Services/ResourceCalculationService.php | 31 +- ...dentity_to_ptero_resource_reservations.php | 87 ++ ...5_000002_normalize_dynamic_option_keys.php | 98 ++ routes/api.php | 9 - tests/AGENTS.md | 2 +- tests/Feature/AvailabilityApiTest.php | 10 +- tests/Feature/ReservationApiTest.php | 490 --------- tests/Unit/CartItemDeletedListenerTest.php | 125 +-- tests/Unit/InvoicePaidListenerTest.php | 131 --- tests/Unit/NodeSelectionServiceTest.php | 24 +- .../ReservationConfigurationServiceTest.php | 68 ++ tests/Unit/ReservationServiceTest.php | 966 ++++-------------- tests/Unit/ResourceCalculationServiceTest.php | 13 +- tests/Unit/StoreReservationRequestTest.php | 174 ---- 42 files changed, 1769 insertions(+), 6080 deletions(-) delete mode 100644 Http/Controllers/Api/ReservationController.php delete mode 100644 Http/Requests/StoreReservationRequest.php delete mode 100644 Listeners/InvoicePaidListener.php delete mode 100644 Listeners/ServiceCreatedListener.php create mode 100644 Services/ReservationConfigurationService.php create mode 100644 database/migrations/2026_07_25_000001_add_checkout_identity_to_ptero_resource_reservations.php create mode 100644 database/migrations/2026_07_25_000002_normalize_dynamic_option_keys.php delete mode 100644 tests/Feature/ReservationApiTest.php delete mode 100644 tests/Unit/InvoicePaidListenerTest.php create mode 100644 tests/Unit/ReservationConfigurationServiceTest.php delete mode 100644 tests/Unit/StoreReservationRequestTest.php diff --git a/01-DATABASE.md b/01-DATABASE.md index f452f36..bbe7c73 100644 --- a/01-DATABASE.md +++ b/01-DATABASE.md @@ -1,579 +1,58 @@ # Database Schema -> **Related docs**: [02-SERVICES.md](02-SERVICES.md) (services that use these tables) +The extension owns four live tables: ---- +| Table | Purpose | +|---|---| +| `ptero_resource_reservations` | Authoritative cart-to-provisioning capacity holds | +| `ptero_audit_logs` | Extension action history | +| `ptero_alert_configs` | Per-location alert thresholds | +| `ptero_alert_delivery_logs` | Alert delivery outcomes | -## Tables Overview +`ptero_pricing_configs` is retired. Paymenter `config_options.metadata` is the pricing source of truth. -``` -┌─────────────────────────────────────────────────────────────────┐ -│ ptero_resource_reservations │ -├─────────────────────────────────────────────────────────────────┤ -│ Temporary holds on resources during checkout (15-min TTL) │ -│ Links cart items → reserved resources → specific nodes │ -└─────────────────────────────────────────────────────────────────┘ - -┌─────────────────────────────────────────────────────────────────┐ -│ ptero_pricing_configs │ -├─────────────────────────────────────────────────────────────────┤ -│ Per-product pricing configuration │ -│ Slider limits, step sizes, pricing model parameters │ -└─────────────────────────────────────────────────────────────────┘ - -┌─────────────────────────────────────────────────────────────────┐ -│ ptero_audit_logs │ -├─────────────────────────────────────────────────────────────────┤ -│ Tracks configuration changes for accountability │ -│ Who changed what, when, and previous values │ -└─────────────────────────────────────────────────────────────────┘ - -┌─────────────────────────────────────────────────────────────────┐ -│ ptero_alert_configs │ -├─────────────────────────────────────────────────────────────────┤ -│ Alert thresholds and notification preferences │ -│ Per-location capacity warnings │ -└─────────────────────────────────────────────────────────────────┘ -``` - ---- - -## Migration 1: Resource Reservations - -**File**: `2025_01_01_000001_create_ptero_resource_reservations_table.php` - -```php -id(); - - // Unique token for tracking reservation - $table->string('token', 64)->unique(); - - // Link to cart (nullable - cleared after checkout) - $table->unsignedBigInteger('cart_item_id')->nullable(); - - // Link to service (set after provisioning) - $table->unsignedBigInteger('service_id')->nullable(); - - // Link to user for tracking - $table->unsignedBigInteger('user_id')->nullable(); - - // Pterodactyl references - $table->unsignedInteger('node_id'); - $table->unsignedInteger('location_id'); - - // Reserved resources (all in MB except CPU) - $table->unsignedInteger('memory'); // MB - $table->unsignedBigInteger('disk'); // MB - $table->unsignedInteger('cpu'); // Percentage (100 = 1 core) - - // Pricing snapshot at reservation time - $table->decimal('calculated_price', 10, 2); - $table->json('pricing_breakdown'); - - // Status tracking - $table->enum('status', [ - 'pending', // Cart item exists, awaiting payment - 'confirmed', // Payment received, server created - 'expired', // TTL exceeded without payment - 'cancelled' // User removed from cart - ])->default('pending'); - - // Admin notes - $table->text('admin_notes')->nullable(); - - // Timestamps - $table->timestamp('expires_at'); - $table->timestamps(); - - // Indexes for efficient queries - $table->index(['node_id', 'status', 'expires_at'], 'idx_node_pending'); - $table->index(['cart_item_id']); - $table->index(['status', 'expires_at'], 'idx_cleanup'); - $table->index(['location_id', 'status']); - $table->index(['user_id', 'status']); - $table->index(['created_at']); - - // Foreign keys - $table->foreign('cart_item_id') - ->references('id') - ->on('cart_items') - ->onDelete('set null'); - - $table->foreign('service_id') - ->references('id') - ->on('services') - ->onDelete('set null'); - - $table->foreign('user_id') - ->references('id') - ->on('users') - ->onDelete('set null'); - }); - } - - public function down(): void - { - Schema::dropIfExists('ptero_resource_reservations'); - } -}; -``` - -### Reservation Status Flow - -``` -┌─────────┐ cart item ┌─────────┐ payment ┌───────────┐ -│ (none) │ ──────────────▶ │ pending │ ────────────▶ │ confirmed │ -└─────────┘ └─────────┘ └───────────┘ - │ - ┌────────────┴────────────┐ - ▼ ▼ - ┌─────────┐ ┌───────────┐ - │ expired │ │ cancelled │ - │ (TTL) │ │ (user) │ - └─────────┘ └───────────┘ -``` +## Resource reservations -Reservation lifecycle: `pending → confirmed | expired | cancelled`. +The base table is created by `2025_01_01_000001_create_ptero_resource_reservations_table.php`. The server-owned checkout identity is added by `2026_07_25_000001_add_checkout_identity_to_ptero_resource_reservations.php`. ---- +### Identity -## Migration 2: Pricing Configs +| Column | Meaning | +|---|---| +| `cart_item_id`, `cart_id` | Original cart identity; the item FK becomes null when checkout clears the cart | +| `server_extension_id`, `panel_identity` | Paymenter provisioner identity and SHA-256 of its normalized panel URL | +| `service_id`, `user_id` | Assigned atomically at checkout/login | +| `product_id`, `plan_id`, `quantity`, `currency_code` | Purchase identity | +| `configuration_payload` | Canonical immutable checkout snapshot, including customer, cart, server extension, hashed panel identity, node, and selected options | +| `configuration_fingerprint` | SHA-256 of the canonical payload | +| `pricing_version`, `formula_version`, `calculated_price` | Pricing provenance | +| `node_id`, `location_id`, `memory`, `cpu`, `disk` | Reserved placement and limits | -**File**: `2025_01_01_000002_create_ptero_pricing_configs_table.php` +The opaque `token` remains for internal/admin lookup of legacy rows. It is not a customer bearer credential and is never placed in browser, URL, cart, or service state. -```php -id(); - - // Link to Paymenter product - $table->unsignedBigInteger('product_id')->unique(); - - // Pricing model selection - $table->enum('pricing_model', [ - 'linear', - 'tiered', - 'base_addon' - ])->default('linear'); - - // JSON configuration for pricing model - // Structure varies by model - see 07-PRICING-MODELS.md - $table->json('pricing_config'); - - // Memory slider configuration (stored in MB) - $table->unsignedInteger('min_memory')->default(1024); // 1GB - $table->unsignedInteger('max_memory')->default(65536); // 64GB - $table->unsignedInteger('memory_step')->default(1024); // 1GB steps - $table->unsignedInteger('default_memory')->default(4096); // 4GB default - - // CPU slider configuration (percentage: 100 = 1 core) - $table->unsignedInteger('min_cpu')->default(100); // 1 core - $table->unsignedInteger('max_cpu')->default(800); // 8 cores - $table->unsignedInteger('cpu_step')->default(100); // 1 core steps - $table->unsignedInteger('default_cpu')->default(200); // 2 cores default - - // Disk slider configuration (stored in MB) - $table->unsignedInteger('min_disk')->default(10240); // 10GB - $table->unsignedInteger('max_disk')->default(512000); // 500GB - $table->unsignedInteger('disk_step')->default(10240); // 10GB steps - $table->unsignedInteger('default_disk')->default(51200); // 50GB default - - // Feature toggles - $table->boolean('enable_memory_slider')->default(true); - $table->boolean('enable_cpu_slider')->default(true); - $table->boolean('enable_disk_slider')->default(true); - $table->boolean('is_active')->default(true); - - // Customer display customization (labels, tooltips) - $table->json('display_config')->nullable(); - - // Location restrictions (null = all locations allowed) - $table->json('allowed_locations')->nullable(); - - $table->timestamps(); - - // Foreign key - $table->foreign('product_id') - ->references('id') - ->on('products') - ->onDelete('cascade'); - }); - } - - public function down(): void - { - Schema::dropIfExists('ptero_pricing_configs'); - } -}; -``` - -### Display Config JSON Structure - -```json -{ - "memory_label": "RAM", - "cpu_label": "CPU Cores", - "disk_label": "Storage", - "memory_tooltip": "RAM determines how much data your server can hold...", - "cpu_tooltip": "CPU cores determine processing power...", - "disk_tooltip": "Storage space for your server files...", - "price_format": "monthly", - "show_breakdown": true, - "show_savings_badge": true -} +```mermaid +stateDiagram-v2 + [*] --> pending: cart create or edit + pending --> pending: login, checkout bind, provisioning lease + pending --> confirmed: Pterodactyl create succeeds + pending --> expired: hold deadline passes + pending --> cancelled: cart removal or replacement ``` ---- +`provisioning_started_at` and the unguessable `provisioning_lease_id` prevent concurrent or stale create workers from consuming the same hold. `consumed_at` records successful Pterodactyl creation. A failed attempt clears only its matching lease and records `last_provisioning_error`; the capacity remains pending until retry or expiry. -## Migration 3: Audit Logs +`active_cart_item_id` is a generated column that is non-null only for pending rows and has a unique index. This enforces one active hold per cart item. -**File**: `2025_01_01_000003_create_ptero_audit_logs_table.php` +During migration, legacy pending rows without a configuration fingerprint are cancelled. They came from the retired browser/listener token flows and cannot be proved safe. Active carts acquire a fresh server-owned hold on edit or checkout. -```php -id(); - - // Who made the change - $table->unsignedBigInteger('user_id'); - $table->string('user_name'); - $table->string('user_email'); - - // What was changed - $table->string('action'); // created, updated, deleted, cancelled - $table->string('entity_type'); // pricing_config, reservation, alert_config - $table->unsignedBigInteger('entity_id'); - $table->string('entity_name')->nullable(); // Product name, etc. - - // Change details - $table->json('old_values')->nullable(); - $table->json('new_values')->nullable(); - $table->text('description')->nullable(); - - // Request context - $table->string('ip_address', 45)->nullable(); - $table->string('user_agent')->nullable(); - - $table->timestamp('created_at'); - - // Indexes - $table->index(['entity_type', 'entity_id']); - $table->index(['user_id']); - $table->index(['created_at']); - $table->index(['action']); - - // Foreign key - $table->foreign('user_id') - ->references('id') - ->on('users') - ->onDelete('cascade'); - }); - } - - public function down(): void - { - Schema::dropIfExists('ptero_audit_logs'); - } -}; -``` - ---- - -## Migration 4: Alert Configs - -**File**: `2025_01_01_000004_create_ptero_alert_configs_table.php` - -```php -id(); - - // Scope: global (null) or per-location - $table->unsignedInteger('location_id')->nullable(); - $table->string('location_name')->nullable(); - - // Capacity thresholds (percentage) - $table->unsignedTinyInteger('memory_warning_threshold')->default(80); - $table->unsignedTinyInteger('memory_critical_threshold')->default(95); - $table->unsignedTinyInteger('disk_warning_threshold')->default(80); - $table->unsignedTinyInteger('disk_critical_threshold')->default(95); - - // Notification settings - $table->boolean('email_notifications')->default(true); - $table->json('notification_emails')->nullable(); // Array of emails - $table->boolean('webhook_notifications')->default(false); - $table->string('webhook_url')->nullable(); - - // Cooldown to prevent spam - $table->unsignedInteger('cooldown_minutes')->default(60); - $table->timestamp('last_notification_at')->nullable(); - - // Status - $table->boolean('is_active')->default(true); - - $table->timestamps(); - - // Indexes - $table->index(['location_id']); - $table->index(['is_active']); - }); - } - - public function down(): void - { - Schema::dropIfExists('ptero_alert_configs'); - } -}; -``` +## Units ---- - -## Eloquent Models - -### PricingConfig Model - -```php - 'array', - 'display_config' => 'array', - 'allowed_locations' => 'array', - 'enable_memory_slider' => 'boolean', - 'enable_cpu_slider' => 'boolean', - 'enable_disk_slider' => 'boolean', - 'is_active' => 'boolean', - ]; - - public function product(): BelongsTo - { - return $this->belongsTo(\App\Models\Product::class); - } -} -``` - -### ResourceReservation Model - -```php - 'array', - 'expires_at' => 'datetime', - 'calculated_price' => 'decimal:2', - ]; - - public function user(): BelongsTo - { - return $this->belongsTo(\App\Models\User::class); - } - - public function service(): BelongsTo - { - return $this->belongsTo(\App\Models\Service::class); - } - - public function scopePending($query) - { - return $query->where('status', 'pending') - ->where('expires_at', '>', now()); - } - - public function scopeExpired($query) - { - return $query->where('status', 'pending') - ->where('expires_at', '<=', now()); - } -} -``` - -### AuditLog Model - -```php - 'array', - 'new_values' => 'array', - 'created_at' => 'datetime', - ]; -} -``` - -### AlertConfig Model - -```php - 'array', - 'email_notifications' => 'boolean', - 'webhook_notifications' => 'boolean', - 'is_active' => 'boolean', - 'last_notification_at' => 'datetime', - ]; - - public function scopeGlobal($query) - { - return $query->whereNull('location_id'); - } - - public function scopeForLocation($query, int $locationId) - { - return $query->where('location_id', $locationId); - } -} -``` - ---- - -## Index Strategy - -| Table | Index | Purpose | -|-------|-------|---------| -| reservations | `idx_node_pending` | Fast lookup of pending reservations by node | -| reservations | `idx_cleanup` | Efficient expired reservation cleanup | -| reservations | `location_id, status` | Location availability calculations | -| pricing_configs | `product_id` (unique) | One config per product | -| audit_logs | `entity_type, entity_id` | View history for specific entity | -| audit_logs | `created_at` | Time-based filtering | -| alert_configs | `location_id` | Per-location alert lookup | - ---- - -## Data Relationships - -``` -products (Paymenter) - │ - └──< ptero_pricing_configs (1:1) - -users (Paymenter) - │ - ├──< ptero_resource_reservations (1:many) - └──< ptero_audit_logs (1:many) - -cart_items (Paymenter) - │ - └──< ptero_resource_reservations (1:1 while in cart) - -services (Paymenter) - │ - └──< ptero_resource_reservations (1:1 after confirmation) -``` +- Memory and disk: MiB-compatible integer values used by Pterodactyl. +- CPU: percentage limit (`100` = one core of limit), stored for identity and provisioning but not treated as node capacity. +- Money: decimal snapshot in the cart currency. -## Removed / deprecated +## Rollback -- `released` removed in dp-07 (2026-04-22). No service ever set this state. Use `provision_failed` if a post-confirm failure state is needed. +The key-normalization migration is intentionally irreversible: restoring uppercase `MEMORY`, `CPU`, `DISK`, or `LOCATION` keys would make the built-in provisioner ignore slider selections. diff --git a/02-SERVICES.md b/02-SERVICES.md index ce7a06f..d9f9fba 100644 --- a/02-SERVICES.md +++ b/02-SERVICES.md @@ -1,908 +1,64 @@ # Core Services -> **Related docs**: [01-DATABASE.md](01-DATABASE.md) (tables used), [07-PRICING-MODELS.md](07-PRICING-MODELS.md) (pricing details), [08-ALGORITHMS.md](08-ALGORITHMS.md) (node selection) - ---- - -## Service Overview - | Service | Responsibility | -|---------|----------------| -| `ResourceCalculationService` | Real-time Pterodactyl API queries | -| `NodeSelectionService` | Best-fit node allocation algorithm | -| `ReservationService` | Resource holds during checkout | -| `SliderConfigReaderService` | Reads dynamic-slider config payloads for API/frontend use | -| `AuditLogService` | Track admin actions | -| `AlertService` | Capacity notifications | - ---- - -## ResourceCalculationService - -Implements **real-time API approach** (no caching) proven by PteroSync. - -```php -getExtensionConfig(); - $this->apiUrl = rtrim($config['pterodactyl_url'] ?? '', '/'); - $this->apiKey = $config['pterodactyl_api_key'] ?? ''; - } - - /** - * Get available resources for a location (real-time from Pterodactyl API) - */ - public function getLocationAvailability(int $locationId, ?string $excludeReservationToken = null): array - { - $nodes = $this->fetchNodesInLocation($locationId); - - $locationData = [ - 'location_id' => $locationId, - 'nodes' => [], - 'max_available' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], - 'total_capacity' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], - 'total_allocated' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], - ]; - - foreach ($nodes as $nodeWithServers) { - $nodeAvailability = $this->calculateNodeAvailability($nodeWithServers, $excludeReservationToken); - $locationData['nodes'][] = $nodeAvailability; - - // Track maximum available across all nodes - $locationData['max_available']['memory'] = max( - $locationData['max_available']['memory'], - $nodeAvailability['available']['memory'] - ); - $locationData['max_available']['cpu'] = max( - $locationData['max_available']['cpu'], - $nodeAvailability['available']['cpu'] - ); - $locationData['max_available']['disk'] = max( - $locationData['max_available']['disk'], - $nodeAvailability['available']['disk'] - ); - - // Aggregate totals - $locationData['total_capacity']['memory'] += $nodeAvailability['total']['memory']; - $locationData['total_capacity']['cpu'] += $nodeAvailability['total']['cpu']; - $locationData['total_capacity']['disk'] += $nodeAvailability['total']['disk']; - - $locationData['total_allocated']['memory'] += $nodeAvailability['allocated']['memory']; - $locationData['total_allocated']['cpu'] += $nodeAvailability['allocated']['cpu']; - $locationData['total_allocated']['disk'] += $nodeAvailability['allocated']['disk']; - } - - return $locationData; - } - - /** - * Calculate available resources for a specific node - */ - private function calculateNodeAvailability(array $nodeWithServers, ?string $excludeReservationToken = null): array - { - $node = $nodeWithServers['node']; - $servers = $nodeWithServers['servers']; - $pendingReservations = $this->getPendingReservations($node['id'], $excludeReservationToken); - - // buildNodeAvailabilityFromServers validates complete node/server - // resource shapes before calculating totals. The fetch layer also - // rejects duplicate node, server, and location identities so repeated - // upstream records cannot distort capacity. Stock Pterodactyl has no - // node CPU-capacity field, so cpu_threads remains a fail-closed gate. - // Production also requires PR #22's zero-as-unlimited rejection and - // API-key encryption migration; the full PR must be safely rebased. - return $this->buildNodeAvailabilityFromServers($node, $servers, $pendingReservations); - } - - /** - * Test API connection - */ - public function testConnection(): array - { - try { - $response = Http::withHeaders([ - 'Authorization' => 'Bearer ' . $this->apiKey, - 'Accept' => 'application/json', - ])->timeout(10)->get("{$this->apiUrl}/api/application/nodes"); - - if ($response->successful()) { - $data = $response->json(); - return [ - 'success' => true, - 'message' => 'Connection successful', - 'node_count' => count($data['data'] ?? []), - 'panel_version' => $response->header('X-Pterodactyl-Version'), - ]; - } - - return [ - 'success' => false, - 'message' => 'API returned error: ' . $response->status(), - 'details' => $response->json('errors', []), - ]; - } catch (\Exception $e) { - return [ - 'success' => false, - 'message' => 'Connection failed: ' . $e->getMessage(), - ]; - } - } - - /** - * Verify resources are still available (called at payment time) - */ - public function verifyAvailability(int $nodeId, array $requirements, ?string $excludeReservationToken = null): bool - { - $nodes = $this->fetchNodesInLocation($this->getNodeLocation($nodeId)); - $nodeWithServers = collect($nodes)->first(fn ($node) => ($node['node']['id'] ?? null) === $nodeId); - - if (!$nodeWithServers) return false; - - $availability = $this->calculateNodeAvailability($nodeWithServers, $excludeReservationToken); - - return $availability['available']['memory'] >= $requirements['memory'] - && $availability['available']['cpu'] >= $requirements['cpu'] - && $availability['available']['disk'] >= $requirements['disk']; - } - - /** - * Get all locations from Pterodactyl - */ - public function getLocations(): array - { - return $this->fetchAllLocations(); - } - - // --- Private Methods --- - - private function fetchNodesInLocation(int $locationId): array - { - $response = $this->pterodactylGet( - "/api/application/locations/{$locationId}", - ['include' => 'nodes,servers'] - ); - - $nodesData = $this->requireRelationshipData($response, 'nodes'); - $serversData = $this->requireRelationshipData($response, 'servers'); - - $nodesById = []; - foreach ($nodesData as $node) { - $attributes = $this->requireNodeAttributes($node); - if ($attributes['location_id'] !== $locationId) { - throw new \RuntimeException('Pterodactyl API returned a node for an unexpected location.'); - } - $this->rememberUniqueId($nodesById, $attributes['id'], 'included node'); - $nodesById[$attributes['id']] = $attributes; - } - - $serversByNode = []; - $serverIds = []; - foreach ($serversData as $server) { - $attributes = $this->requireServerAttributes($server); - $nodeId = $attributes['node']; - if (! array_key_exists($nodeId, $nodesById)) { - throw new \RuntimeException('Pterodactyl API returned a server for an unknown included node.'); - } - $this->rememberUniqueId($serverIds, $attributes['id'], 'included server'); - $serversByNode[$nodeId][] = $attributes; - } - - $nodes = []; - foreach ($nodesById as $nodeId => $attributes) { - $nodes[] = [ - 'node' => $attributes, - 'servers' => $serversByNode[$nodeId] ?? [], - ]; - } - - return $nodes; - } - - private function rememberUniqueId(array &$seen, int $id, string $resource): void - { - if (array_key_exists($id, $seen)) { - throw new \RuntimeException("Pterodactyl API returned a duplicate {$resource}."); - } - - $seen[$id] = true; - } - - private function getPendingReservations(int $nodeId, ?string $excludeReservationToken = null): array - { - $query = DB::table('ptero_resource_reservations') - ->where('node_id', $nodeId) - ->where('status', 'pending') - ->where('expires_at', '>', now()); - - if ($excludeReservationToken !== null) { - $query->where('token', '!=', $excludeReservationToken); - } - - $result = $query - ->selectRaw('COALESCE(SUM(memory), 0) as memory') - ->selectRaw('COALESCE(SUM(cpu), 0) as cpu') - ->selectRaw('COALESCE(SUM(disk), 0) as disk') - ->first(); - - return [ - 'memory' => (int)$result->memory, - 'cpu' => (int)$result->cpu, - 'disk' => (int)$result->disk, - ]; - } - - private function getNodeLocation(int $nodeId): int - { - $data = $this->pterodactylGet("/api/application/nodes/{$nodeId}"); - $locationId = $data['attributes']['location_id'] ?? null; - if (! is_int($locationId)) { - throw new \RuntimeException("Pterodactyl node {$nodeId} response is missing location_id."); - } - - return $locationId; - } - - private function getExtensionConfig(): array - { - return Extension::where('extension', 'DynamicPterodactyl') - ->first() - ?->settings - ->pluck('value', 'key') - ->toArray() ?? []; - } -} -``` - ---- +|---|---| +| `ReservationConfigurationService` | Build canonical checkout payloads, fingerprints, and service-match proofs | +| `ReservationService` | Own the hold from cart creation through provisioning | +| `ResourceCalculationService` | Read live Pterodactyl memory/disk inventory and pending holds | +| `NodeSelectionService` | Select a non-maintenance node that fits authoritative resources | +| `ConfigOptionSetupService` | Transactionally create normalized native slider options | +| `SliderConfigReaderService` | Read native slider metadata for price previews | +| `AlertService` | Capacity and shortfall notifications | +| `AuditLogService` | Best-effort extension audit writes | -## NodeSelectionService - -Implements **best-fit algorithm with headroom weighting**. See [08-ALGORITHMS.md](08-ALGORITHMS.md) for detailed explanation. - -```php -resourceService = $resourceService; - } - - /** - * Select the best node for given resource requirements - * - * Algorithm: Best-fit with headroom weighting - * - Memory: 50% weight (most commonly upgraded) - * - Disk: 35% weight (harder to migrate) - * - CPU: 15% weight (often unlimited/shared) - */ - public function selectBestNode(int $locationId, array $requirements): ?array - { - $locationData = $this->resourceService->getLocationAvailability($locationId); - - $candidates = []; - - foreach ($locationData['nodes'] as $node) { - // Skip nodes in maintenance mode - if ($node['maintenance_mode'] ?? false) continue; - - // Check if node can accommodate requirements - if ($node['available']['memory'] < $requirements['memory']) continue; - if ($node['available']['cpu'] < $requirements['cpu']) continue; - if ($node['available']['disk'] < $requirements['disk']) continue; - - // Calculate remaining headroom after allocation - $remainingMemory = $node['available']['memory'] - $requirements['memory']; - $remainingCpu = $node['available']['cpu'] - $requirements['cpu']; - $remainingDisk = $node['available']['disk'] - $requirements['disk']; - - // Weighted score: prioritize memory headroom, then disk, then CPU - $memoryScore = ($remainingMemory / max(1, $node['total']['memory'])) * 0.50; - $diskScore = ($remainingDisk / max(1, $node['total']['disk'])) * 0.35; - $cpuScore = ($remainingCpu / max(1, $node['total']['cpu'])) * 0.15; - - $score = $memoryScore + $diskScore + $cpuScore; - - $candidates[] = [ - 'node' => $node, - 'score' => $score, - 'remaining' => [ - 'memory' => $remainingMemory, - 'cpu' => $remainingCpu, - 'disk' => $remainingDisk, - ], - ]; - } - - if (empty($candidates)) { - return null; - } - - // Sort by score descending, return highest - usort($candidates, fn($a, $b) => $b['score'] <=> $a['score']); - - return $candidates[0]['node']; - } - - /** - * Get maximum allocatable resources across a location - */ - public function getMaxAvailable(int $locationId, ?array $locationData = null): array - { - $locationData ??= $this->resourceService->getLocationAvailability($locationId); - if (($locationData['location_id'] ?? null) !== $locationId - || !is_array($locationData['max_available'] ?? null)) { - throw new \RuntimeException('Invalid location availability snapshot.'); - } - - foreach (['memory', 'cpu', 'disk'] as $resource) { - if (!is_int($locationData['max_available'][$resource] ?? null) - || $locationData['max_available'][$resource] < 0) { - throw new \RuntimeException('Invalid location availability snapshot.'); - } - } +## ReservationConfigurationService - return $locationData['max_available']; - } -} -``` +`forCartItem()` rejects partial configurations and quantity greater than one, resolves the selected Pterodactyl location, and records: ---- +- cart, product, plan, quantity, and currency; +- memory, CPU limit, disk, and location; +- all selected config-option values and metadata; +- the exact calculated cart price; +- pricing and formula versions. -## SliderConfigReaderService - -This service is now intentionally thin: it reads `dynamic_slider` ConfigOption metadata and returns the slider/config payload used by the extension API. Pricing math no longer lives in the extension. - -`POST /pricing/calculate` delegates directly to Paymenter core via `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` inside `PricingController`. - ---- +Every RAM, CPU, and disk value comes from either its validated slider selection or the product's static Pterodactyl setting; a missing value fails closed. After node selection, `withNode()` adds the node and `fingerprint()` hashes the canonical JSON. Guest login uses `withCustomer()` while holding the cart and reservation locks, then stores the replacement fingerprint in the same transaction. `assertServiceMatches()` proves the created service still has the same customer, purchase, and resource values before provisioning. ## ReservationService -Handles temporary resource holds with **pessimistic locking** to prevent overselling. - -```php -nodeService = $nodeService; - $this->auditService = $auditService; - $this->ttlMinutes = config('dynamic-pterodactyl.reservation_ttl', 15); - } - - /** - * Create a resource reservation - * - * Uses database transaction with pessimistic locking - * Retries up to 5 times on deadlock - */ - public function create( - int $productId, - int $locationId, - array $resources, - ?int $cartItemId = null, - ?int $userId = null - ): array { - return DB::transaction(function () use ($productId, $locationId, $resources, $cartItemId, $userId) { - // Lock pending reservations for this location - DB::table('ptero_resource_reservations') - ->where('location_id', $locationId) - ->where('status', 'pending') - ->lockForUpdate() - ->get(); - - // Find best node - $node = $this->nodeService->selectBestNode($locationId, $resources); - - if (!$node) { - throw new \RuntimeException('No node with sufficient resources available'); - } - - // Create reservation - // Create reservation - $token = Str::random(64); - $expiresAt = now()->addMinutes($this->ttlMinutes); - - $id = DB::table('ptero_resource_reservations')->insertGetId([ - 'token' => $token, - 'cart_item_id' => $cartItemId, - 'user_id' => $userId, - 'node_id' => $node['node_id'], - 'location_id' => $locationId, - 'memory' => $resources['memory'], - 'cpu' => $resources['cpu'], - 'disk' => $resources['disk'], - 'calculated_price' => 0, - 'pricing_breakdown' => json_encode([]), - 'status' => 'pending', - 'expires_at' => $expiresAt, - 'created_at' => now(), - 'updated_at' => now(), - ]); - - return [ - 'id' => $id, - 'token' => $token, - 'node_id' => $node['node_id'], - 'node_name' => $node['name'], - 'expires_at' => $expiresAt->toIso8601String(), - 'ttl_minutes' => $this->ttlMinutes, - 'pricing' => $pricing, - ]; - }, 5); // 5 retry attempts for deadlock - } - - /** - * Confirm a reservation (after successful payment) - */ - public function confirm(string $token, int $serviceId): bool - { - return DB::table('ptero_resource_reservations') - ->where('token', $token) - ->where('status', 'pending') - ->update([ - 'status' => 'confirmed', - 'service_id' => $serviceId, - 'updated_at' => now(), - ]) > 0; - } - - /** - * Cancel a reservation - */ - public function cancel(string $token, ?string $reason = null, bool $isAdminAction = false): bool - { - $reservation = $this->getByToken($token); - - if (!$reservation) return false; - - $result = DB::table('ptero_resource_reservations') - ->where('token', $token) - ->where('status', 'pending') - ->update([ - 'status' => 'cancelled', - 'admin_notes' => $reason, - 'updated_at' => now(), - ]) > 0; - - if ($result && $isAdminAction) { - $this->auditService->log('cancelled', 'reservation', $reservation->id, [ - 'reason' => $reason, - 'resources' => [ - 'memory' => $reservation->memory, - 'cpu' => $reservation->cpu, - 'disk' => $reservation->disk, - ], - ]); - } - - return $result; - } - - /** - * Extend reservation TTL - */ - public function extend(string $token, int $additionalMinutes = 15): bool - { - return DB::table('ptero_resource_reservations') - ->where('token', $token) - ->where('status', 'pending') - ->update([ - 'expires_at' => DB::raw("DATE_ADD(expires_at, INTERVAL {$additionalMinutes} MINUTE)"), - 'updated_at' => now(), - ]) > 0; - } - - /** - * Get reservation by token - */ - public function getByToken(string $token): ?object - { - return DB::table('ptero_resource_reservations') - ->where('token', $token) - ->first(); - } - - /** - * Get reservation by cart item - */ - public function getByCartItem(int $cartItemId): ?object - { - return DB::table('ptero_resource_reservations') - ->where('cart_item_id', $cartItemId) - ->where('status', 'pending') - ->first(); - } - - /** - * Get all reservations with filters (for admin) - */ - public function getAll(array $filters = []): \Illuminate\Support\Collection - { - $query = DB::table('ptero_resource_reservations') - ->leftJoin('users', 'ptero_resource_reservations.user_id', '=', 'users.id') - ->select([ - 'ptero_resource_reservations.*', - 'users.name as user_name', - 'users.email as user_email', - ]); - - if (!empty($filters['status'])) { - $query->where('status', $filters['status']); - } - if (!empty($filters['location_id'])) { - $query->where('location_id', $filters['location_id']); - } - if (!empty($filters['node_id'])) { - $query->where('node_id', $filters['node_id']); - } - if (!empty($filters['user_id'])) { - $query->where('ptero_resource_reservations.user_id', $filters['user_id']); - } - - return $query->orderBy('created_at', 'desc')->get(); - } - - /** - * Get reservation statistics - */ - public function getStatistics(string $period = '30d'): array - { - $startDate = match($period) { - '24h' => now()->subDay(), - '7d' => now()->subDays(7), - '30d' => now()->subDays(30), - '90d' => now()->subDays(90), - default => now()->subDays(30), - }; - - $stats = DB::table('ptero_resource_reservations') - ->where('created_at', '>=', $startDate) - ->selectRaw('status, COUNT(*) as count') - ->groupBy('status') - ->pluck('count', 'status') - ->toArray(); - - $revenue = DB::table('ptero_resource_reservations') - ->where('created_at', '>=', $startDate) - ->where('status', 'confirmed') - ->sum('calculated_price'); - - $avgResources = DB::table('ptero_resource_reservations') - ->where('created_at', '>=', $startDate) - ->where('status', 'confirmed') - ->selectRaw('AVG(memory) as avg_memory, AVG(cpu) as avg_cpu, AVG(disk) as avg_disk') - ->first(); - - $total = array_sum($stats); - $confirmed = $stats['confirmed'] ?? 0; - $expired = $stats['expired'] ?? 0; - $cancelled = $stats['cancelled'] ?? 0; - - return [ - 'period' => $period, - 'total' => $total, - 'by_status' => $stats, - 'confirmed_revenue' => $revenue, - 'conversion_rate' => ($confirmed + $expired + $cancelled) > 0 - ? round($confirmed / ($confirmed + $expired + $cancelled) * 100, 1) - : 0, - 'average_resources' => [ - 'memory' => round($avgResources->avg_memory ?? 0), - 'cpu' => round($avgResources->avg_cpu ?? 0), - 'disk' => round($avgResources->avg_disk ?? 0), - ], - ]; - } - - /** - * Cleanup expired reservations (called by scheduled job) - */ - public function cleanupExpired(): int - { - return DB::table('ptero_resource_reservations') - ->where('status', 'pending') - ->where('expires_at', '<', now()) - ->update([ - 'status' => 'expired', - 'updated_at' => now(), - ]); - } -} -``` +| Method | Boundary | +|---|---| +| `reserveForCartItem()` | Create, reuse, or atomically replace one cart hold | +| `transferCartOwnership()` | Move guest holds with the cart during login | +| `bindCartItemToService()` | Attach the matching hold and extend it through invoice due time | +| `beginProvisioning()` | Lock, validate, and lease the pending hold | +| `completeProvisioning()` | Consume it only after Pterodactyl accepts the server | +| `failProvisioning()` | Clear the attempt lease while retaining capacity | +| `cancelForCartItem()` | Release an unbound hold before cart-item deletion | ---- +All state-changing paths use transactions and row locks. Customer input never supplies a reservation token or node. -## AuditLogService - -```php -insertGetId([ - 'user_id' => $user?->id ?? 0, - 'user_name' => $user?->name ?? 'System', - 'user_email' => $user?->email ?? 'system@localhost', - 'action' => $action, - 'entity_type' => $entityType, - 'entity_id' => $entityId, - 'entity_name' => $entityName, - 'old_values' => $oldValues ? json_encode($oldValues) : null, - 'new_values' => $newValues ? json_encode($newValues) : null, - 'description' => $description, - 'ip_address' => Request::ip(), - 'user_agent' => Request::userAgent(), - 'created_at' => now(), - ]); - } - - /** - * Get audit logs with filters - */ - public function getLogs(array $filters = [], int $limit = 50): \Illuminate\Support\Collection - { - $query = DB::table('ptero_audit_logs'); - - if (!empty($filters['entity_type'])) { - $query->where('entity_type', $filters['entity_type']); - } - if (!empty($filters['entity_id'])) { - $query->where('entity_id', $filters['entity_id']); - } - if (!empty($filters['user_id'])) { - $query->where('user_id', $filters['user_id']); - } - if (!empty($filters['action'])) { - $query->where('action', $filters['action']); - } - if (!empty($filters['date_from'])) { - $query->where('created_at', '>=', $filters['date_from']); - } - if (!empty($filters['date_to'])) { - $query->where('created_at', '<=', $filters['date_to']); - } - - return $query->orderBy('created_at', 'desc')->limit($limit)->get(); - } - - /** - * Get logs for a specific entity - */ - public function getEntityHistory(string $entityType, int $entityId): \Illuminate\Support\Collection - { - return $this->getLogs([ - 'entity_type' => $entityType, - 'entity_id' => $entityId, - ], 100); - } -} -``` - ---- - -## AlertService - -```php -resourceService = $resourceService; - } - - /** - * Check all locations for capacity alerts - */ - public function checkCapacityAlerts(): void - { - $alertConfigs = DB::table('ptero_alert_configs') - ->where('is_active', true) - ->get(); - - foreach ($alertConfigs as $config) { - $this->checkAlertConfig($config); - } - } - - private function checkAlertConfig(object $config): void - { - // Skip if in cooldown - if ($config->last_notification_at && - now()->diffInMinutes($config->last_notification_at) < $config->cooldown_minutes) { - return; - } - - try { - if ($config->location_id) { - $locations = [$config->location_id]; - } else { - $locations = collect($this->resourceService->getLocations())->pluck('id'); - } - - foreach ($locations as $locationId) { - $availability = $this->resourceService->getLocationAvailability($locationId); - $alerts = $this->checkThresholds($availability, $config); - - if (!empty($alerts)) { - $this->sendNotifications($config, $availability, $alerts); - - DB::table('ptero_alert_configs') - ->where('id', $config->id) - ->update(['last_notification_at' => now()]); - } - } - } catch (\Exception $e) { - \Log::error('Alert check failed', [ - 'config_id' => $config->id, - 'error' => $e->getMessage(), - ]); - } - } - - private function checkThresholds(array $availability, object $config): array - { - $alerts = []; - - $memoryUtilization = $availability['total_capacity']['memory'] > 0 - ? ($availability['total_allocated']['memory'] / $availability['total_capacity']['memory']) * 100 - : 0; - - $diskUtilization = $availability['total_capacity']['disk'] > 0 - ? ($availability['total_allocated']['disk'] / $availability['total_capacity']['disk']) * 100 - : 0; - - if ($memoryUtilization >= $config->memory_critical_threshold) { - $alerts[] = ['type' => 'critical', 'resource' => 'memory', 'utilization' => $memoryUtilization]; - } elseif ($memoryUtilization >= $config->memory_warning_threshold) { - $alerts[] = ['type' => 'warning', 'resource' => 'memory', 'utilization' => $memoryUtilization]; - } - - if ($diskUtilization >= $config->disk_critical_threshold) { - $alerts[] = ['type' => 'critical', 'resource' => 'disk', 'utilization' => $diskUtilization]; - } elseif ($diskUtilization >= $config->disk_warning_threshold) { - $alerts[] = ['type' => 'warning', 'resource' => 'disk', 'utilization' => $diskUtilization]; - } - - return $alerts; - } - - private function sendNotifications(object $config, array $availability, array $alerts): void - { - $locationName = $config->location_name ?? 'All Locations'; - - if ($config->email_notifications && !empty($config->notification_emails)) { - $emails = json_decode($config->notification_emails, true); - // Send email notification - // Implementation depends on your mail setup - } - - if ($config->webhook_notifications && $config->webhook_url) { - Http::post($config->webhook_url, [ - 'location' => $locationName, - 'alerts' => $alerts, - 'availability' => $availability, - 'timestamp' => now()->toIso8601String(), - ]); - } - } - - /** - * Send test notification - */ - public function sendTestNotification(object $config): void - { - $testAlerts = [ - ['type' => 'test', 'resource' => 'memory', 'utilization' => 85], - ]; - - $testAvailability = [ - 'location_id' => $config->location_id ?? 0, - 'total_capacity' => ['memory' => 65536, 'disk' => 512000], - 'total_allocated' => ['memory' => 55705, 'disk' => 409600], - ]; - - $this->sendNotifications($config, $testAvailability, $testAlerts); - } -} -``` +Memory and disk capacity are computed as: ---- +`effective total - existing server allocation - unexpired pending reservations` -## Scheduled Jobs +Memory and disk honor Pterodactyl overallocation. Reads are uncached and the cluster snapshot path batches node/server data. -### CleanupExpiredReservations +Pterodactyl does not expose authoritative node CPU capacity. Therefore: -```php -cleanupExpired(); - - if ($count > 0) { - \Log::info("Cleaned up {$count} expired reservations"); - } - } -} -``` +## Configuration setup -Register in scheduler: -```php -// In App\Console\Kernel or extension boot -$schedule->job(new CleanupExpiredReservations)->everyMinute(); -$schedule->job(new CheckCapacityAlerts)->everyFiveMinutes(); -``` +Native option environment keys are lowercase: `memory`, `cpu`, `disk`, and `location`. The normalization migration updates existing options and service properties. `ExtensionHelper::getServiceProperties()` serializes `ServiceConfig.slider_value` for dynamic sliders so a config row cannot overwrite the numeric property with null. diff --git a/03-API.md b/03-API.md index 74ae356..0f1b000 100644 --- a/03-API.md +++ b/03-API.md @@ -1,723 +1,34 @@ -# API Endpoints +# API Surface -> **Related docs**: [02-SERVICES.md](02-SERVICES.md) (services called by controllers), [06-FRONTEND.md](06-FRONTEND.md) (JavaScript that calls these APIs) +All routes are registered from `routes/api.php`. ---- +## Authenticated customer routes -## Route Definitions +Prefix: `/api/dynamic-pterodactyl` +Middleware: `web`, `auth`, `throttle:30,1` -### Public API Routes (Guest-Compatible Checkout) +| Method | Route | Response | +|---|---|---| +| GET | `/availability/{locationId}` | Aggregate location maxima; no node identity | +| POST | `/pricing/calculate` | Core-owned dynamic-slider price preview | +| GET | `/pricing/config/{productId}` | Native slider configuration | -```php -middleware(['web', 'auth', 'throttle:30,1'])->group(function () { - // Availability - Route::get('/availability/{locationId}', [AvailabilityController::class, 'getByLocation']); +Prefix: `/api/dynamic-pterodactyl/admin` +Middleware: `web`, `auth`, `EnsureUserIsAdmin`, `throttle:30,1` - // Pricing - Route::post('/pricing/calculate', [PricingController::class, 'calculate']); - Route::get('/pricing/config/{productId}', [PricingController::class, 'getConfig']); -}); +| Method | Route | Purpose | +|---|---|---| +| GET | `/reservations` | Paginated reservation inventory | +| POST | `/reservations/{token}/cancel` | Cancel an unbound pending row with a reason | +| GET | `/capacity` | Cluster capacity summary | +| GET | `/availability/{locationId}/nodes` | Raw per-node details | -// Reservation endpoints — throttled (10 req/min) for checkout-retry burst tolerance -Route::prefix('api/dynamic-pterodactyl')->middleware(['web', 'checkout', 'throttle:10,1'])->group(function () { - Route::post('/reservation', [ReservationController::class, 'create']); - Route::get('/reservation/{token}', [ReservationController::class, 'get']); - Route::delete('/reservation/{token}', [ReservationController::class, 'cancel']); - Route::post('/reservation/{token}/extend', [ReservationController::class, 'extend']); -}); -``` +## Removed customer reservation API -> Pricing config no longer uses `ptero_pricing_configs`. It now uses native Paymenter ConfigOption rows with `type='dynamic_slider'` and `metadata.resource_type`. +There is no customer create/get/cancel/extend reservation endpoint. Capacity holds are created synchronously by server-side cart listeners. This removes browser idempotency, bearer tokens, session storage, URL state, and client-selected node ownership from the protocol. -### Admin API Routes - -```php -middleware(['web', 'auth', EnsureUserIsAdmin::class, 'throttle:30,1']) - ->group(function () { - Route::get('/reservations', [AdminReservationController::class, 'index']); - Route::post('/reservations/{token}/cancel', [AdminReservationController::class, 'cancel']); - Route::get('/capacity', [AdminCapacityController::class, 'summary']); - Route::get('/availability/{locationId}/nodes', [AvailabilityController::class, 'getNodes']); - }); -``` - -### Removed Endpoints - -The following endpoints were previously documented but either never shipped or were retired by dp-09/dp-11: -- `POST /api/dynamic-pterodactyl/pricing/validate-config` -- `POST /api/dynamic-pterodactyl/admin/pricing/import` -- `GET /api/dynamic-pterodactyl/admin/pricing/export` -- `POST /api/dynamic-pterodactyl/admin/reservations/{token}/extend` -- `POST /api/dynamic-pterodactyl/admin/reservations/cleanup` -- `POST /api/dynamic-pterodactyl/admin/test-connection` -- `GET /api/dynamic-pterodactyl/admin/statistics` -- `GET /api/dynamic-pterodactyl/admin/dashboard` - -Future readers who find references in old commits can ignore them. - ---- - -## Endpoint Reference - -### GET /api/dynamic-pterodactyl/availability/{locationId} - -Get maximum available resources for a location. - -**Response:** -```json -{ - "success": true, - "data": { - "location_id": 1, - "max_memory": 32768, - "max_cpu": 800, - "max_disk": 204800, - "node_count": 3, - "has_capacity": true, - "resource_capacity": { - "memory": true, - "cpu": true, - "disk": true - } - } -} -``` - -`has_capacity` is conservative: it is only `true` when memory, CPU, and disk are all positive. `resource_capacity` exposes the per-resource booleans the frontend can use to explain which resource is exhausted. - -### POST /api/dynamic-pterodactyl/pricing/calculate - -Calculate price for a resource configuration by delegating to Paymenter core pricing primitives. - -**Request:** -```json -{ - "product_id": 5, - "plan_id": 12, - "memory": 8192, - "cpu": 400, - "disk": 102400 -} -``` - -`plan_id` is optional; when omitted, the first plan (sorted by `sort`) for the product is used. Only the slider resource types configured on the product are required — requests missing a configured slider return `422`. Requests with a `plan_id` belonging to a different product also return `422`. Products with no `dynamic_slider` config options return `404`. - -`PricingController::calculate()` resolves the selected plan, adds `Plan::dynamicSliderBasePrice()` once when at least one slider is in scope, and sums each slider's `ConfigOption::calculateDynamicPriceDelta(...)` result into the response payload. - -**Response (200 OK):** -```json -{ - "success": true, - "data": { - "total": 24.00, - "breakdown": [ - { "resource_type": "memory", "label": "Memory", "value": 8192, "display_value": "8 GB", "price": 4.00, "pricing_model": "linear" }, - { "resource_type": "cpu", "label": "CPU", "value": 400, "display_value": "4 cores", "price": 8.00, "pricing_model": "linear" }, - { "resource_type": "disk", "label": "Disk", "value": 102400, "display_value": "100 GB", "price": 7.00, "pricing_model": "linear" } - ], - "model": "linear" - } -} -``` - -The shared base price is included in `total` but not duplicated in each breakdown row. - -**Response (422 — foreign `plan_id`):** -```json -{ - "success": false, - "message": "Selected plan does not belong to this product" -} -``` - -### GET /api/dynamic-pterodactyl/pricing/config/{productId} - -Get pricing configuration and slider limits for a product. - -**Response:** -```json -{ - "success": true, - "data": { - "product_id": 5, - "pricing_model": "linear", - "sliders": { - "memory": { - "enabled": true, - "min": 1024, - "max": 65536, - "step": 1024, - "default": 4096 - }, - "cpu": { - "enabled": true, - "min": 100, - "max": 800, - "step": 100, - "default": 200 - }, - "disk": { - "enabled": true, - "min": 10240, - "max": 512000, - "step": 10240, - "default": 51200 - } - }, - "display": { - "memory_label": "RAM", - "cpu_label": "CPU Cores", - "disk_label": "Storage", - "show_breakdown": true - }, - "allowed_locations": null - } -} -``` - -### POST /api/dynamic-pterodactyl/reservation - -Create a resource reservation. Guests are allowed so the first capacity hold can be created on the product page before login. The throttle still protects the route: authenticated requests key by user and guest requests fall back to IP. - -**Headers:** -- `Idempotency-Key` *(optional, preferred)* — 8-64 characters, alphanumeric plus hyphen. When reused by the same user while an existing reservation is still `pending` or `confirmed`, the API returns the original reservation instead of creating a duplicate hold. - -**Request:** -```json -{ - "product_id": 5, - "location_id": 1, - "memory": 8192, - "cpu": 400, - "disk": 102400, - "cart_item_id": 123, - "idempotency_key": "checkout-req-123" -} -``` - -`cart_item_id` is optional. Product-page slider changes happen before a cart row exists, so the frontend can reserve capacity with only `product_id`, `location_id`, and the slider resources. When the item is later added to cart, Paymenter stores the returned token in `cart_items.checkout_config.dp_reservation_token` and confirms it during checkout. - -**Validation rules:** -- Product must have `dynamic_slider` config options for dynamic reservations, otherwise the request is rejected with `422` and `This product is not configured for dynamic reservations`. -- `location_id` must be one of the product's configured `location_ids` when that product setting is present. -- Each configured resource must be present in the payload. -- Extra resource fields not configured on the product are rejected. -- Each selected resource must stay within the slider's `min`/`max` bounds and match its configured `step` increment. -- `Idempotency-Key` header or `idempotency_key` body field must match `^[A-Za-z0-9-]{8,64}$` when supplied. - -### Reservation lifecycle - -The shipped flow is now: - -1. Customer changes a `dynamic_slider` value on the product page. -2. The parent Alpine `dynamicSliderGroup` component debounces 500ms, POSTs `/api/dynamic-pterodactyl/reservation`, and stores the returned token in `sessionStorage`. -3. Add-to-cart copies that token into `cart_items.checkout_config.dp_reservation_token`. -4. `App\Livewire\Cart::checkout()` creates the `Service`, then calls `ReservationService::confirm($token, $service->id, Auth::user())`. -5. If confirmation fails, checkout deletes the just-created service and surfaces a capacity-expired error instead of overselling. - -**Response:** -```json -{ - "success": true, - "data": { - "id": 456, - "token": "abc123def456...", - "node_id": 1, - "node_name": "Node-US-01", - "expires_at": "2025-11-28T12:30:00Z", - "ttl_minutes": 15, - "pricing": { - "total": 0, - "breakdown": [], - "model": "stored" - } - } -} -``` - -### GET /api/dynamic-pterodactyl/reservation/{token} - -Get reservation details. - -**Response:** -```json -{ - "success": true, - "data": { - "id": 456, - "token": "abc123def456...", - "status": "pending", - "node_id": 1, - "location_id": 1, - "memory": 8192, - "cpu": 400, - "disk": 102400, - "calculated_price": 0, - "expires_at": "2025-11-28T12:30:00Z", - "created_at": "2025-11-28T12:15:00Z" - } -} -``` - -### DELETE /api/dynamic-pterodactyl/reservation/{token} - -Cancel a reservation. - -**Response:** -```json -{ - "success": true, - "message": "Reservation cancelled" -} -``` - -### POST /api/dynamic-pterodactyl/reservation/{token}/extend - -Extend reservation TTL. - -**Request:** -```json -{ - "minutes": 15 -} -``` - -**Response:** -```json -{ - "success": true, - "data": { - "expires_at": "2025-11-28T12:45:00Z" - } -} -``` - -### GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes - -Get detailed per-node availability for admin diagnostics. - -**Response:** -```json -{ - "success": true, - "data": { - "location_id": 1, - "nodes": [ - { - "node_id": 1, - "name": "Node-US-01", - "total": { "memory": 65536, "cpu": 1600, "disk": 512000 }, - "allocated": { "memory": 32768, "cpu": 800, "disk": 256000 }, - "reserved": { "memory": 4096, "cpu": 200, "disk": 20480 }, - "available": { "memory": 28672, "cpu": 600, "disk": 235520 }, - "utilization": { "memory": 56.2, "disk": 54.0 }, - "server_count": 12 - } - ], - "total_capacity": { "memory": 131072, "cpu": 3200, "disk": 1024000 }, - "total_allocated": { "memory": 65536, "cpu": 1600, "disk": 512000 } - } -} -``` - ---- - -## Controllers - -### AvailabilityController - -```php -resourceService = $resourceService; - $this->nodeService = $nodeService; - } - - public function getByLocation(int $locationId): JsonResponse - { - try { - $locationData = $this->resourceService->getLocationAvailability($locationId); - $maxAvailable = $this->nodeService->getMaxAvailable($locationId, $locationData); - $resourceCapacity = [ - 'memory' => $maxAvailable['memory'] > 0, - 'cpu' => $maxAvailable['cpu'] > 0, - 'disk' => $maxAvailable['disk'] > 0, - ]; - - return response()->json([ - 'success' => true, - 'data' => [ - 'location_id' => $locationId, - 'max_memory' => $maxAvailable['memory'], - 'max_cpu' => $maxAvailable['cpu'], - 'max_disk' => $maxAvailable['disk'], - 'node_count' => count($locationData['nodes']), - 'has_capacity' => $resourceCapacity['memory'] && $resourceCapacity['cpu'] && $resourceCapacity['disk'], - 'resource_capacity' => $resourceCapacity, - ], - ]); - } catch (\Throwable $e) { - report($e); - - return response()->json([ - 'success' => false, - 'message' => 'Failed to fetch availability', - ], 500); - } - } - - public function getNodes(int $locationId): JsonResponse - { - try { - $locationData = $this->resourceService->getLocationAvailability($locationId); - - return response()->json([ - 'success' => true, - 'data' => $locationData, - ]); - } catch (\Throwable $e) { - report($e); - - return response()->json([ - 'success' => false, - 'message' => 'Failed to fetch node details', - ], 500); - } - } -} -``` - -### PricingController - -```php -sliderConfigReader = $sliderConfigReader; - } - - public function calculate(Request $request): JsonResponse - { - // Phase 1: validate product_id (static) - $request->validate(['product_id' => 'required|integer|exists:products,id']); - $product = Product::query()->with(['configOptions', 'plans'])->findOrFail($request->integer('product_id')); - - $sliderOptions = $product->configOptions->where('type', 'dynamic_slider')->whereNull('parent_id'); - - if ($sliderOptions->isEmpty()) { - return response()->json(['success' => false, 'message' => 'This product is not configured for dynamic pricing'], 404); - } - - // Phase 2: build dynamic validation rules from configured sliders - $rules = ['plan_id' => 'nullable|integer|exists:plans,id']; - foreach ($sliderOptions as $option) { - $rules[$option->getMetadata('resource_type', strtolower($option->name))] = 'required|integer|min:1'; - } - $validated = array_merge(['product_id' => $product->id], $request->validate($rules)); - - try { - try { - $plan = $this->resolvePlan($product, $validated['plan_id'] ?? null); - } catch (\InvalidArgumentException $e) { - return response()->json(['success' => false, 'message' => $e->getMessage()], 422); - } - - $breakdown = []; - $total = 0.0; - $hasSlider = false; - - foreach ($sliderOptions as $option) { - $resourceType = $option->getMetadata('resource_type', strtolower($option->name)); - $value = (float) ($validated[$resourceType] ?? 0); - if ($value <= 0) continue; - - $hasSlider = true; - $price = $option->calculateDynamicPriceDelta($value, $plan->billing_period, $plan->billing_unit); - $breakdown[] = [ - 'resource_type' => $resourceType, - 'label' => $option->name, - 'value' => $value, - 'display_value' => $option->formatValueForDisplay($value), - 'price' => round($price, 2), - 'pricing_model' => $option->getMetadata('pricing.model', 'linear'), - ]; - $total += $price; - } - - if ($hasSlider) { - $total += $plan->dynamicSliderBasePrice(); - } - - return response()->json([ - 'success' => true, - 'data' => [ - 'total' => round($total, 2), - 'breakdown' => $breakdown, - 'model' => $sliderOptions->first()?->getMetadata('pricing.model', 'linear') ?? 'linear', - ], - ]); - } catch (\Exception $e) { - Log::error('DynamicPterodactyl price calculation failed', ['error' => $e->getMessage()]); - $payload = ['success' => false, 'message' => 'Price calculation failed']; - if (config('app.debug')) $payload['error'] = $e->getMessage(); - return response()->json($payload, 500); - } - } - - public function getConfig(int $productId): JsonResponse - { - $config = $this->sliderConfigReader->getConfig($productId); - - if (! $config['has_config']) { - return response()->json(['success' => false, 'message' => 'No dynamic slider config options found for this product'], 404); - } - - return response()->json(['success' => true, 'data' => ['product_id' => $productId, 'sliders' => $config['sliders']]]); - } - - public function validate(Request $request): JsonResponse - { - return response()->json(['success' => false, 'errors' => ['Pricing validation endpoint has been retired']], 410); - } - - private function resolvePlan(Product $product, ?int $planId): Plan { /* ... */ } -} -``` - -### ReservationController - -```php -reservationService = $reservationService; - } - - public function create(StoreReservationRequest $request): JsonResponse - { - $validated = $request->validated(); - $resources = [ - 'memory' => (int) ($validated['memory'] ?? 0), - 'cpu' => (int) ($validated['cpu'] ?? 0), - 'disk' => (int) ($validated['disk'] ?? 0), - ]; - - try { - $reservation = $this->reservationService->create( - productId: $validated['product_id'], - locationId: $validated['location_id'], - resources: $resources, - cartItemId: $validated['cart_item_id'] ?? null, - userId: $request->user()?->id, - idempotencyKey: $validated['idempotency_key'] ?? null, - ); - - return response()->json([ - 'success' => true, - 'data' => $reservation, - ]); - } catch (\RuntimeException $e) { - return response()->json([ - 'success' => false, - 'message' => $e->getMessage(), - ], 422); - } catch (\Exception $e) { - return response()->json([ - 'success' => false, - 'message' => 'Failed to create reservation', - ], 500); - } - } - - public function get(string $token): JsonResponse - { - $reservation = $this->reservationService->getByToken($token); - - if (!$reservation) { - return response()->json([ - 'success' => false, - 'message' => 'Reservation not found', - ], 404); - } - - // Only allow owner or admin to view - if ($reservation->user_id !== auth()->id() && !auth()->user()->is_admin) { - return response()->json([ - 'success' => false, - 'message' => 'Unauthorized', - ], 403); - } - - return response()->json([ - 'success' => true, - 'data' => $reservation, - ]); - } - - public function cancel(string $token): JsonResponse - { - $reservation = $this->reservationService->getByToken($token); - - if (!$reservation) { - return response()->json([ - 'success' => false, - 'message' => 'Reservation not found', - ], 404); - } - - if ($reservation->user_id !== auth()->id() && !auth()->user()->is_admin) { - return response()->json([ - 'success' => false, - 'message' => 'Unauthorized', - ], 403); - } - - $result = $this->reservationService->cancel($token); - - return response()->json([ - 'success' => $result, - 'message' => $result ? 'Reservation cancelled' : 'Failed to cancel reservation', - ]); - } - - public function extend(Request $request, string $token): JsonResponse - { - $validated = $request->validate([ - 'minutes' => 'integer|min:1|max:60', - ]); - - $reservation = $this->reservationService->getByToken($token); - - if (!$reservation) { - return response()->json([ - 'success' => false, - 'message' => 'Reservation not found', - ], 404); - } - - if ($reservation->user_id !== auth()->id() && !auth()->user()->is_admin) { - return response()->json([ - 'success' => false, - 'message' => 'Unauthorized', - ], 403); - } - - $result = $this->reservationService->extend($token, $validated['minutes'] ?? 15); - - if ($result) { - $updated = $this->reservationService->getByToken($token); - return response()->json([ - 'success' => true, - 'data' => [ - 'expires_at' => $updated->expires_at, - ], - ]); - } - - return response()->json([ - 'success' => false, - 'message' => 'Failed to extend reservation', - ], 500); - } -} -``` - ---- - -## Error Response Format - -All error responses follow this structure: - -```json -{ - "success": false, - "message": "Human-readable error message", - "error": "Technical details (only in non-production)", - "errors": { - "field_name": ["Validation error message"] - } -} -``` - -### HTTP Status Codes - -| Code | Meaning | -|------|---------| -| 200 | Success | -| 400 | Bad request (invalid parameters) | -| 401 | Unauthorized (not logged in) | -| 403 | Forbidden (not allowed) | -| 404 | Not found | -| 422 | Unprocessable (validation failed or business rule violation) | -| 500 | Server error | - ---- - -## Rate Limiting - -Consider implementing rate limiting for availability endpoints: - -```php -// In RouteServiceProvider or middleware -RateLimiter::for('dynamic-pterodactyl', function ($request) { - return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); -}); -``` - -Pterodactyl API limit: **240 requests/minute** — our endpoints should stay well under this. +Controllers validate and authorize, then delegate to services. Customer errors must never include raw upstream Pterodactyl bodies or node details. diff --git a/04-EVENTS.md b/04-EVENTS.md index 3ce348a..afdbc3c 100644 --- a/04-EVENTS.md +++ b/04-EVENTS.md @@ -1,401 +1,53 @@ -# Event Hook Integration +# Checkout and Provisioning Lifecycle -> **Related docs**: [02-SERVICES.md](02-SERVICES.md) (services called by handlers), [README.md](README.md) (system flow) +The reservation is server-owned from cart mutation through Pterodactyl creation. ---- +```mermaid +sequenceDiagram + participant Cart + participant Hold as ReservationService + participant Pay as Paymenter payment + participant Ptero as Pterodactyl provisioner -## Overview - -The companion extension integrates with Paymenter's event system to: -1. Create reservations when items are added to cart -2. Cancel reservations when items are removed -3. Confirm reservations when payment succeeds -4. Track service creation - -``` -┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ -│ Cart Item │────▶│ Checkout │────▶│ Invoice │────▶│ Service │ -│ Created │ │ (wait) │ │ Paid │ │ Created │ -└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ - │ │ │ - ▼ ▼ ▼ - ┌───────────┐ ┌───────────┐ ┌───────────┐ - │ Create │ │ Verify & │ │ Link │ - │Reservation│ │ Confirm │ │ Service │ - │ (15 min) │ │Reservation│ │ ID │ - └───────────┘ └───────────┘ └───────────┘ -``` - ---- - -## Event Listener Registration - -In the extension's `boot()` method: - -```php -registerEventListeners(); -} - -private function registerEventListeners(): void -{ - // Cart item created - create reservation - Event::listen(\App\Events\CartItem\Created::class, function ($event) { - $this->handleCartItemCreated($event); - }); - - // Cart item deleted - cancel reservation - Event::listen(\App\Events\CartItem\Deleted::class, function ($event) { - $this->handleCartItemDeleted($event); - }); - - // Invoice paid - confirm reservation - Event::listen(\App\Events\Invoice\Updated::class, function ($event) { - $this->handleInvoiceUpdated($event); - }); - - // Service created - link reservation - Event::listen(\App\Events\Service\Created::class, function ($event) { - $this->handleServiceCreated($event); - }); -} -``` - ---- - -## Event Handlers - -### CartItem Created - -When a user adds a dynamic Pterodactyl product to their cart: -1. Check if product has a pricing config (is a dynamic product) -2. Extract resource selections from configurable options -3. Create a reservation with 15-minute TTL -4. Store reservation token in cart item properties - -```php -cartItem; - $properties = $cartItem->properties ?? []; - - // Check if this is a dynamic Pterodactyl product - if (!$this->isDynamicPterodactylProduct($cartItem->product_id)) { - return; - } - - // Check if required properties exist (from configurable options) - if (!isset($properties['memory'], $properties['cpu'], $properties['disk'], $properties['location'])) { - \Log::debug('CartItem missing required properties for dynamic reservation', [ - 'cart_item_id' => $cartItem->id, - 'properties' => array_keys($properties), - ]); - return; - } - - try { - $reservationService = app(ReservationService::class); - - $reservation = $reservationService->create( - productId: $cartItem->product_id, - locationId: (int) $properties['location'], - resources: [ - 'memory' => (int) $properties['memory'], - 'cpu' => (int) $properties['cpu'], - 'disk' => (int) $properties['disk'], - ], - cartItemId: $cartItem->id, - userId: auth()->id() - ); - - // Store reservation token in cart item for later reference - // Using underscore prefix to indicate internal properties - $cartItem->update([ - 'properties' => array_merge($properties, [ - '_reservation_token' => $reservation['token'], - '_selected_node' => $reservation['node_id'], - '_calculated_price' => $reservation['pricing']['total'], - ]), - ]); - - \Log::info('Created resource reservation for cart item', [ - 'cart_item_id' => $cartItem->id, - 'reservation_token' => substr($reservation['token'], 0, 8) . '...', - 'node_id' => $reservation['node_id'], - 'expires_at' => $reservation['expires_at'], - ]); - - } catch (\Exception $e) { - // Log error but don't block the cart operation - // User can still checkout, but without guaranteed resources - \Log::error('Failed to create resource reservation', [ - 'cart_item_id' => $cartItem->id, - 'error' => $e->getMessage(), - ]); - } -} -``` - -### CartItem Deleted - -When a user removes an item from their cart: - -```php -cartItem; - $properties = $cartItem->properties ?? []; - - // Check if this cart item had a reservation - if (!isset($properties['_reservation_token'])) { - return; - } - - try { - $reservationService = app(ReservationService::class); - $reservationService->cancel($properties['_reservation_token']); - - \Log::info('Cancelled reservation for deleted cart item', [ - 'cart_item_id' => $cartItem->id, - 'reservation_token' => substr($properties['_reservation_token'], 0, 8) . '...', - ]); - - } catch (\Exception $e) { - \Log::error('Failed to cancel reservation', [ - 'token' => substr($properties['_reservation_token'], 0, 8) . '...', - 'error' => $e->getMessage(), - ]); - } -} -``` - -### Invoice Updated (Payment) - -When an invoice status changes to 'paid': -1. Find associated services -2. Verify resources are still available (final check) -3. Confirm the reservation -4. Link reservation to service - -```php -invoice; - - // Only process when invoice becomes paid - if ($invoice->status !== 'paid') { - return; - } - - // Check if status actually changed to paid (not already paid) - if (!$invoice->wasChanged('status')) { - return; - } - - foreach ($invoice->items as $item) { - // Skip items without a service - if (!$item->service_id) { - continue; - } - - $service = $item->service; - if (!$service) { - continue; - } - - $properties = $service->properties ?? []; - - // Check if this service has a reservation - if (!isset($properties['_reservation_token'])) { - continue; - } - - try { - $reservationService = app(ReservationService::class); - $resourceService = app(ResourceCalculationService::class); - - $reservation = $reservationService->getByToken($properties['_reservation_token']); - - if (!$reservation) { - \Log::warning('Reservation not found for paid invoice', [ - 'service_id' => $service->id, - 'invoice_id' => $invoice->id, - ]); - continue; - } - - // CRITICAL: Final availability verification - $available = $resourceService->verifyAvailability( - $reservation->node_id, - [ - 'memory' => $reservation->memory, - 'cpu' => $reservation->cpu, - 'disk' => $reservation->disk, - ] - ); - - if (!$available) { - // This should rarely happen, but we need to handle it - \Log::error('Resources no longer available for paid service', [ - 'service_id' => $service->id, - 'node_id' => $reservation->node_id, - 'memory' => $reservation->memory, - 'cpu' => $reservation->cpu, - 'disk' => $reservation->disk, - ]); - - // TODO: Notify admin for manual intervention - // The server will still be created by Pterodactyl extension, - // but may fail due to insufficient resources - continue; - } - - // Confirm the reservation - $reservationService->confirm($properties['_reservation_token'], $service->id); - - \Log::info('Confirmed reservation for paid service', [ - 'service_id' => $service->id, - 'node_id' => $reservation->node_id, - ]); - - } catch (\Exception $e) { - \Log::error('Failed to confirm reservation', [ - 'service_id' => $service->id, - 'error' => $e->getMessage(), - ]); - } - } -} -``` - -### Service Created - -Track when the Pterodactyl server is actually created: - -```php -service; - $properties = $service->properties ?? []; - - if (!isset($properties['_reservation_token'])) { - return; - } - - \Log::info('Service created with reservation', [ - 'service_id' => $service->id, - 'reservation_token' => substr($properties['_reservation_token'], 0, 8) . '...', - 'product_id' => $service->product_id, - ]); - - // The reservation should already be confirmed by handleInvoiceUpdated - // This is just for logging/tracking purposes -} + Cart->>Hold: reserveForCartItem + Cart->>Hold: transferCartOwnership on login + Cart->>Hold: bindCartItemToService + Pay->>Ptero: dispatch CreateJob + Ptero->>Hold: beginProvisioning + Ptero->>Ptero: create exact node and limits + Ptero->>Hold: completeProvisioning ``` ---- +## Cart create and update -## Helper Method +`CartItem\Created` and `CartItem\Updated` use `CartItemCreatedListener`. The listener delegates to `reserveForCartItem()` and intentionally lets errors bubble. Paymenter wraps `Cart::add()` and quantity edits in a database transaction, so insufficient capacity or an unavailable extension rolls back the cart mutation. -```php -where('product_id', $productId) - ->where('is_active', true) - ->exists(); -} -``` - ---- +## Guest login -## Reservation TTL Extension +`UserAuthListener` updates the cart owner and calls `transferCartOwnership()` in one database transaction. Existing non-null ownership must match; it is never silently overwritten. -When user reaches the checkout/payment page, extend their reservation to prevent expiry: +## Checkout -```php -cart; - - foreach ($cart->items as $item) { - $properties = $item->properties ?? []; - - if (isset($properties['_reservation_token'])) { - $reservationService = app(ReservationService::class); - $reservationService->extend($properties['_reservation_token'], 15); - } - } -}); -``` +- proves the current cart snapshot matches the stored fingerprint; +- proves product, plan, quantity, and currency match the service; +- transfers a guest owner if needed; +- assigns `service_id`; +- extends expiry through the invoice due time. -Alternatively, the frontend JavaScript can call the extend API endpoint when the user reaches checkout. +Missing extension, missing hold, expired hold, or identity drift aborts and rolls back checkout. ---- +## Cart removal -## Graceful Degradation +`CartItem\Deleting` calls `cancelForCartItem()` while the relationship still exists. Bound checkout rows are not cancelled. Clearing the cart after checkout nulls the cart-item FK but preserves `cart_id` and `service_id`. -The event handlers are designed to fail gracefully: +## Payment and provisioning -| Scenario | Behavior | -|----------|----------| -| Pterodactyl API down | Log error, allow cart operation | -| No nodes available | Log error, allow cart operation | -| Reservation expired | Log warning, server creation may fail | -| Database error | Log error, allow cart operation | +There is no invoice-paid reservation listener. Paymenter dispatches provisioning before `Invoice\Paid`, so confirmation there would be too late. -**Philosophy**: Don't block the customer's purchase flow. If reservations fail, the worst case is the server creation might fail later, which can be handled manually. +The built-in Pterodactyl `createServer()` calls `beginProvisioning()` directly. The returned context overrides the actual lowercase `node`, `location`, `memory`, `cpu`, and `disk` settings. The row remains pending while the external request runs. ---- - -## Event List Reference - -Paymenter events used: - -| Event | When Fired | -|-------|------------| -| `CartItem\Created` | Item added to cart | -| `CartItem\Updated` | Item quantity/properties changed | -| `CartItem\Deleted` | Item removed from cart | -| `Invoice\Created` | Invoice generated | -| `Invoice\Updated` | Invoice status changes | -| `Service\Created` | Service provisioned | - -Full event list: https://paymenter.org/development/event-list - ---- - -## Testing Events - -To manually test event handlers: - -```php -// In tinker or a test -$cartItem = \App\Models\CartItem::find(123); - -// Manually fire the event -event(new \App\Events\CartItem\Created($cartItem)); - -// Check logs for handler execution -``` +After a successful server create, `completeProvisioning()` marks it confirmed and records `consumed_at`. Failure clears only the provisioning lease. If the server exists on retry, the provisioner reconciles the row and returns the existing server instead of duplicating it. diff --git a/06-FRONTEND.md b/06-FRONTEND.md index 489a677..d6052b7 100644 --- a/06-FRONTEND.md +++ b/06-FRONTEND.md @@ -1,48 +1,19 @@ # Frontend Architecture -## Overview +Paymenter core owns the native `dynamic_slider` input, price preview, Livewire state, and checkout form. -The customer-facing product-configuration UI uses Paymenter's native `dynamic_slider` config option type plus one core-owned Alpine coordinator: `resources/js/dynamic-slider-group.js`. The extension still does not ship its own JS bundle, but its reservation API is now called directly from Paymenter's checkout theme. +The slider is a native range input with Alpine state and Livewire entanglement. It supports Page Up/Down, Home/End, an accessible value description, a live price output, and server-side validation of min/max values. -## Slider component +The browser does not create or store reservations. There is: -**File**: `themes/default/views/components/form/configoption.blade.php` (lines 79–248) +- no reservation fetch request; +- no reservation token in session storage; +- no token mirrored into Livewire checkout configuration; +- no token in URL state; +- no client-selected node. -The slider is a native HTML `` wrapped in an Alpine.js component (`x-data`). Key characteristics: +Capacity is checked synchronously when the configured product is added or edited in the cart. A failure is surfaced through Paymenter's `DisplayException` notification handling and the cart mutation is rolled back. -- **Data shape**: The Alpine component holds `value` (current slider integer), `min`, `max`, `step`, and `displayValue` (formatted with a unit suffix). These are passed as Blade component props from the config option metadata. -- **Client-side price calculation**: `calculatePrice()` is a pure Alpine.js function that reads the pricing model from metadata (linear / tiered / base_addon) and computes the per-slider price delta locally. Price display updates instantaneously while a separate request manages capacity reservations. -- **Livewire entanglement**: The slider value is synced to Livewire via `$wire.entangle('{{ $name }}').live`. This allows the parent Livewire checkout component to re-render the cart total when the slider changes. -- **Reservation signalling**: after each debounced change, the child slider dispatches `slider-change` with `{ resourceType, value }` so the wrapper can submit a single reservation request for the whole product. +Pricing preview remains client-friendly, but Paymenter core recalculates the authoritative price when building the cart and service. -## `dynamicSliderGroup` Alpine coordinator - -**File**: `resources/js/dynamic-slider-group.js` - -This wrapper lives around the product checkout form only when the product contains at least one `dynamic_slider` config option. - -- Holds shared state for all sliders on one product page: `memory`, `cpu`, `disk`, `token`, `error`, `loading`. -- Restores any prior token from `sessionStorage` using `dp_reservation_token__`. -- Listens for child `slider-change` events, debounces 500ms, and POSTs `/api/dynamic-pterodactyl/reservation` with `product_id`, `plan_id`, `location_id`, and the full resource snapshot. -- Persists the latest token back to `sessionStorage` and mirrors it into `checkoutConfig.dp_reservation_token` before Add-to-cart. -- Treats `422` as a blocking capacity error, retries `429` with backoff, and degrades gracefully on `5xx`/network failures. - -## Checkout persistence - -Once Add-to-cart runs, the reservation token moves out of browser-only state and into `cart_items.checkout_config.dp_reservation_token`. That key is copied onto the created service during checkout and confirmed immediately by `App\Livewire\Cart::checkout()`. - -## Accessibility gaps (tracked in dp-10) - -- The live price display lacks `aria-live="polite"`. Screen readers do not announce price changes when the slider moves. -- Progress indicators in the admin panel (`dashboard.blade.php`, `node-monitoring.blade.php`) lack `role="progressbar"` and `aria-value*` attributes. - -## Admin UI - -The admin panel uses Filament v4 exclusively. The extension registers pages and resources via standard Filament discovery — no custom asset injection. See `05-ADMIN-UI.md` for the admin surface inventory. - -## What this extension does NOT own on the frontend - -- The `` HTML and Alpine.js component — owned by Paymenter core themes. -- The `calculateDynamicPrice()` method — in `app/Models/ConfigOption.php` (core). -- Cart total rendering — core Livewire Cart component. -- Checkout form — core Livewire Checkout component. +The extension ships no customer JavaScript bundle. Admin pages use Filament 5 and extension Blade views. diff --git a/08-ALGORITHMS.md b/08-ALGORITHMS.md index bc3722c..3f233fd 100644 --- a/08-ALGORITHMS.md +++ b/08-ALGORITHMS.md @@ -1,368 +1,34 @@ -# Algorithms +# Allocation and Concurrency Algorithms -> **Related docs**: [02-SERVICES.md](02-SERVICES.md) (service implementations) +## Availability ---- +For memory and disk: -## Node Selection Algorithm +`available = effective node total - Pterodactyl server allocations - live pending holds` -### Goal +Effective totals apply Pterodactyl's memory/disk overallocation percentage. Pending means `status = pending` and `expires_at > now()`. -Select the best node that can accommodate requested resources while maintaining balanced utilization across the cluster. +CPU is not hard inventory because the Pterodactyl application API exposes server CPU limits but no authoritative node CPU capacity. CPU remains part of the immutable purchase and provisioned server limit, while availability returns null and `cpu_capacity_enforced = false`. -### Approach: Best-Fit with Headroom Weighting +## Node selection -Not just "first available" or "most available" — we use **weighted headroom scoring** to: -1. Ensure the node CAN fit the request -2. Prefer nodes with better capacity distribution -3. Weight resources by importance (memory > disk > CPU) +1. Fetch live nodes for the chosen location. +2. Subtract unexpired pending holds. +3. Reject maintenance nodes. +4. Reject nodes that cannot fit memory or disk. +5. Score remaining relative headroom: + - memory: 60%; + - disk: 40%. +6. Choose the highest score. -### Why These Weights? +When replacing a cart hold, the previous token is excluded from availability calculation and the old row is cancelled in the same transaction. -| Resource | Weight | Rationale | -|----------|--------|-----------| -| Memory | 50% | Most commonly upgraded; hard to migrate | -| Disk | 35% | Harder to expand; data migration is slow | -| CPU | 15% | Often shared/burstable; easier to oversell | +## Concurrency -### Algorithm Steps +`reserveForCartItem()` locks pending rows for the location before selecting and inserting. A generated unique active-cart-item column prevents two live holds for one cart item. -``` -1. FILTER: Remove nodes that cannot fit the request - - Skip nodes in maintenance mode - - Skip nodes with insufficient memory - - Skip nodes with insufficient CPU - - Skip nodes with insufficient disk +`beginProvisioning()` locks the service-bound reservation. A five-minute `provisioning_started_at` lease rejects a second worker. The hold expiry is extended through the lease so scheduled cleanup cannot release capacity during the Pterodactyl request. -2. SCORE: Calculate weighted headroom for each candidate - For each node: - remaining_memory = available_memory - requested_memory - remaining_cpu = available_cpu - requested_cpu - remaining_disk = available_disk - requested_disk - - memory_score = (remaining_memory / total_memory) × 0.50 - disk_score = (remaining_disk / total_disk) × 0.35 - cpu_score = (remaining_cpu / total_cpu) × 0.15 - - total_score = memory_score + disk_score + cpu_score +The row stays pending until the external create succeeds. This closes the gap where a confirmed row stopped counting before a server existed. After success, Pterodactyl is the allocated-capacity source and the reservation becomes confirmed. -3. SELECT: Choose node with highest score -``` - -### Visual Example - -``` -Request: 8GB RAM, 2 cores, 50GB disk - -Node A: 32GB total, 16GB available → fits, remaining 8GB -Node B: 64GB total, 20GB available → fits, remaining 12GB -Node C: 32GB total, 6GB available → SKIP (can't fit 8GB) - -Scoring (memory only for simplicity): -Node A: 8/32 = 0.25 × 0.50 = 0.125 -Node B: 12/64 = 0.1875 × 0.50 = 0.094 - -Winner: Node A (better relative headroom despite smaller total) -``` - -### Pseudocode - -```php -function selectBestNode(locationId, requirements): - nodes = getNodesInLocation(locationId) - candidates = [] - - for node in nodes: - if node.maintenance_mode: - continue - - available = calculateAvailable(node) - - if available.memory < requirements.memory: - continue - if available.cpu < requirements.cpu: - continue - if available.disk < requirements.disk: - continue - - remaining = { - memory: available.memory - requirements.memory, - cpu: available.cpu - requirements.cpu, - disk: available.disk - requirements.disk, - } - - score = (remaining.memory / node.total.memory) * 0.50 - + (remaining.disk / node.total.disk) * 0.35 - + (remaining.cpu / node.total.cpu) * 0.15 - - candidates.append({ node, score, remaining }) - - if candidates.empty: - return null - - return candidates.sortByScoreDesc().first().node -``` - -### Edge Cases - -| Scenario | Handling | -|----------|----------| -| No nodes in location | Return `null`, let caller handle | -| All nodes in maintenance | Return `null` | -| Exact fit (0 remaining) | Score = 0, still valid candidate | -| Single node location | That node wins if it fits | - ---- - -## Availability Calculation - -### Components of "Available" Resources - -``` -Available = Total Capacity - - Already Allocated (existing servers) - - Pending Reservations (checkout in progress) -``` - -### Pterodactyl Overallocation - -Pterodactyl allows overallocation for memory and disk: - -``` -Effective Total = Base Capacity × (1 + Overallocation% / 100) - -Example: - Base memory: 64GB - Overallocation: 50% - Effective: 64 × 1.5 = 96GB allocatable -``` - -CPU is NOT overallocated (uses thread count × 100). - -### Calculation Flow - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Pterodactyl API │ -├─────────────────────────────────────────────────────────────────┤ -│ GET /api/application/locations/{id}?include=nodes,servers │ -│ │ -│ Returns: │ -│ - node.memory (base capacity) │ -│ - node.memory_overallocate (percentage) │ -│ - node.disk (base capacity) │ -│ - node.disk_overallocate (percentage) │ -│ - servers[].limits.memory (allocated per server) │ -│ - servers[].limits.cpu │ -│ - servers[].limits.disk │ -└─────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────┐ -│ Local Database Query │ -├─────────────────────────────────────────────────────────────────┤ -│ SELECT SUM(memory), SUM(cpu), SUM(disk) │ -│ FROM ptero_resource_reservations │ -│ WHERE node_id = ? AND status = 'pending' │ -│ AND expires_at > NOW() │ -└─────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────┐ -│ Final Calculation │ -├─────────────────────────────────────────────────────────────────┤ -│ effective_total = base × (1 + overallocate/100) │ -│ allocated = SUM(server.limits) │ -│ reserved = SUM(pending_reservations) │ -│ available = effective_total - allocated - reserved │ -└─────────────────────────────────────────────────────────────────┘ -``` - ---- - -## Concurrency Control - -### The Problem - -Two customers selecting resources simultaneously could both be promised the same capacity, leading to overselling. - -``` -Timeline: - T0: Customer A checks availability → 8GB available - T1: Customer B checks availability → 8GB available - T2: Customer A reserves 8GB → succeeds - T3: Customer B reserves 8GB → should fail, but might succeed without locking -``` - -### Solution: Pessimistic Locking - -Lock pending reservations for the location before checking availability and creating new reservation. - -```php -DB::transaction(function () use ($locationId, $requirements) { - // Lock all pending reservations for this location - // This prevents concurrent transactions from reading stale data - DB::table('ptero_resource_reservations') - ->where('location_id', $locationId) - ->where('status', 'pending') - ->lockForUpdate() // ← Key: exclusive lock - ->get(); - - // Now calculate availability (includes locked rows) - $node = $this->nodeService->selectBestNode($locationId, $requirements); - - if (!$node) { - throw new \RuntimeException('No capacity available'); - } - - // Create reservation (within same transaction) - return $this->createReservation($node, $requirements); -}, 5); // ← Retry up to 5 times on deadlock -``` - -### Why `lockForUpdate()`? - -| Lock Type | Behavior | -|-----------|----------| -| Shared (`sharedLock()`) | Multiple readers allowed, blocks writes | -| Exclusive (`lockForUpdate()`) | Blocks all other access until commit | - -We need exclusive because we're reading AND writing based on the read. - -### Deadlock Handling - -With pessimistic locking, deadlocks can occur if two transactions lock in different orders. Laravel's transaction retry handles this: - -```php -DB::transaction(function () { - // ... locking logic ... -}, 5); // Retry 5 times with exponential backoff -``` - -### Race Condition Timeline (With Locking) - -``` -Timeline: - T0: Customer A begins transaction, locks location 1 - T1: Customer B begins transaction, waits for lock... - T2: Customer A calculates availability, creates reservation - T3: Customer A commits, releases lock - T4: Customer B acquires lock, calculates (sees A's reservation) - T5: Customer B sees reduced availability, acts accordingly -``` - ---- - -## Reservation Lifecycle - -### State Machine - -``` - ┌──────────────┐ - │ (start) │ - └──────┬───────┘ - │ add to cart - ▼ - ┌──────────────┐ - ┌───────│ pending │───────┐ - │ └──────┬───────┘ │ - │ │ │ - TTL expires payment succeeds user cancels - │ │ │ - ▼ ▼ ▼ - ┌──────────┐ ┌───────────┐ ┌───────────┐ - │ expired │ │ confirmed │ │ cancelled │ - └──────────┘ └───────────┘ └───────────┘ - │ │ │ - └──────────────┴───────────────┘ - │ - ▼ - ┌──────────────┐ - │ (released) │ ← resources back in pool - └──────────────┘ -``` - -### TTL Management - -**Default TTL**: 15 minutes (configurable) - -**Extension**: Customers can extend once when they reach checkout, adding another 15 minutes. - -**Cleanup Job**: Runs every minute to mark expired reservations. - -```php -// Cleanup query -UPDATE ptero_resource_reservations -SET status = 'expired', updated_at = NOW() -WHERE status = 'pending' AND expires_at < NOW() -``` - -### Final Verification - -Even with reservations, we do a **final check** at payment time: - -```php -// In invoice payment handler -$stillAvailable = $resourceService->verifyAvailability( - $reservation->node_id, - [ - 'memory' => $reservation->memory, - 'cpu' => $reservation->cpu, - 'disk' => $reservation->disk, - ] -); - -if (!$stillAvailable) { - // Edge case: node capacity changed (admin removed node, etc.) - // Log error, notify admin, but don't block payment - // Server creation will fail at Pterodactyl level -} -``` - -This catches edge cases like: -- Admin removing a node -- Another admin manually creating servers -- Pterodactyl capacity changes - ---- - -## Performance Considerations - -### API Call Frequency - -| Scenario | API Calls | -|----------|-----------| -| Location dropdown change | 1 (nodes in location) | -| Create reservation | 1 (verify node capacity) | -| Price calculation | 0 (local only) | -| Cleanup job | 0 (local only) | - -Pterodactyl rate limit: **240 requests/minute** — we stay well under this. - -### Database Query Optimization - -Key indexes on `ptero_resource_reservations`: - -```sql --- Fast pending reservation lookup by node -INDEX idx_node_pending (node_id, status, expires_at) - --- Fast cleanup of expired -INDEX idx_cleanup (status, expires_at) - --- Location availability calculation -INDEX (location_id, status) -``` - -### Caching (Intentionally Avoided) - -We chose **real-time API** over caching because: -1. Stale cache = overselling risk -2. Cache invalidation complexity -3. Proven by PteroSync in production -4. Pterodactyl API is fast enough - -If latency becomes an issue, consider: -- Edge caching with 30-second TTL (accept slight staleness) -- WebSocket for real-time updates -- Background refresh with optimistic UI +Pterodactyl `external_id = service.id` provides reconciliation on retry: an existing server completes the bound reservation instead of creating another. diff --git a/09-IMPLEMENTATION.md b/09-IMPLEMENTATION.md index 367a6bf..2b94936 100644 --- a/09-IMPLEMENTATION.md +++ b/09-IMPLEMENTATION.md @@ -1,303 +1,60 @@ -# Implementation Guide - -> **Related docs**: All other documents in this folder - ---- - -## File Structure - -``` -extension/Others/DynamicPterodactyl/ -├── DynamicPterodactyl.php # Main extension class -│ -├── database/ -│ └── migrations/ -│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php -│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php -│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php -│ └── 2025_01_01_000004_create_ptero_alert_configs_table.php -│ -├── Admin/ -│ ├── Pages/ -│ │ ├── Dashboard.php -│ │ ├── NodeMonitoring.php -│ │ ├── AuditLogPage.php -│ │ └── SetupWizard.php -│ └── Resources/ -│ ├── ReservationResource.php -│ └── AlertConfigResource.php -│ -├── Http/ -│ └── Controllers/ -│ ├── Api/ -│ │ ├── AvailabilityController.php -│ │ ├── PricingController.php -│ │ └── ReservationController.php -│ └── Admin/ -│ ├── AdminReservationController.php -│ └── AdminCapacityController.php -│ -├── Models/ -│ ├── ResourceReservation.php -│ ├── AuditLog.php -│ └── AlertConfig.php -│ -├── resources/ -│ └── views/ -│ └── admin/ -│ ├── dashboard.blade.php -│ ├── node-monitoring.blade.php -│ ├── audit-log.blade.php -│ └── setup-wizard.blade.php -│ -├── routes/ -│ └── api.php -│ -└── Services/ - ├── ResourceCalculationService.php - ├── NodeSelectionService.php - ├── ReservationService.php - ├── PricingCalculatorService.php - ├── AuditLogService.php - ├── AlertService.php - └── ConfigOptionSetupService.php -``` - ---- - -## Implementation Roadmap - -| Phase | Status | Reference | -|---|---|---| -| Database schema | ✅ Shipped | dp-08 idempotency + drop_released migrations | -| Service layer | ✅ Shipped | dp-09 cleanup; 8 services live | -| API endpoints | ✅ Shipped | dp-05 admin API; dp-08 reservation hardening | -| Filament admin UI | ✅ Shipped | dp-13 SetupWizard atomicity | -| Pricing model | ✅ Delegated to core | core `DynamicSliderPricingRule` (dp-core-01) | -| Frontend slider | ✅ Shipped | dp-10 a11y; dp-core-02 Blade partial | -| Capacity alerts | ✅ Shipped | dp-12 scheduled task + email; dp-17 delivery log | -| Authorization hardening | ✅ Shipped | dp-11 policy + cart-item ownership | - -## Current Backlog - -Improvement items from the 2026-04-26 audit pass: - -- **dp-14**: Rate-limit reservation endpoints to 10 req/min per authenticated user — ✅ Shipped (PR #17) -- **dp-16**: Documentation sync: align 03-API + 05-ADMIN-UI + 09-IMPLEMENTATION with post-dp-13 architecture — ✅ Shipped (this PR) -- **dp-17**: Alert delivery log + `AlertDeliveryFailed` escalation event — ✅ Shipped (PR #18) -- **dp-18**: Capacity-fanout performance: batch Pterodactyl reads in `ResourceCalculationService` to reduce O(locations × nodes) API calls in admin views — ✅ Shipped (PR #20) - ---- - -## Testing Strategy - -### Unit Tests - -Test individual service methods in isolation. - -```php -class PricingCalculatorServiceTest extends TestCase -{ - public function test_linear_pricing_calculation() - { - $service = new PricingCalculatorService(); - - // Mock pricing config - $this->mockPricingConfig(1, [ - 'pricing_model' => 'linear', - 'pricing_config' => json_encode([ - 'base_price' => 5, - 'memory_per_gb' => 0.50, - 'cpu_per_core' => 2.00, - 'disk_per_gb' => 0.02, - ]), - ]); - - $result = $service->calculate(1, [ - 'memory' => 8192, // 8GB - 'cpu' => 400, // 4 cores - 'disk' => 102400, // 100GB - ]); - - $this->assertEquals(19.00, $result['total']); - $this->assertEquals('linear', $result['model']); - } - - public function test_tiered_pricing_with_multiple_tiers() - { - // ... - } - - public function test_base_addon_with_no_overage() - { - // ... - } -} -``` - -### Integration Tests - -Integration tests against a real or mocked Pterodactyl API are not yet implemented. The suite is unit-level with limited feature coverage. - -Current test coverage under `tests/Unit/` is mostly mocked service/listener validation. `tests/Feature/` currently covers admin API authorization/response behavior plus the skipped SetupWizard placeholder. - -### Feature Tests - -Test full HTTP request/response cycles. - -```php -class AdminApiTest extends TestCase -{ - public function test_admin_capacity_endpoint_returns_structure() - { - $response = $this->actingAs($this->admin) - ->getJson('/api/dynamic-pterodactyl/admin/capacity'); - - $response->assertOk() - ->assertJsonStructure([ - 'success', - 'data' => [ - 'locations', - 'generated_at', - ], - ]); - } -} -``` - -### Browser Tests - -No browser/E2E suite is implemented in this extension yet. Frontend slider verification is currently manual. - -## SetupWizard Atomicity + Audit Reliability (dp-13) - -`createDynamicSliderOptions()` is wrapped in `DB::transaction()`. Mid-batch failures (pricing rule throw, FK violation, transient DB error) roll back all writes atomically. The audit entry is written post-commit; failure is structured-logged and reported but does not affect the transaction outcome. - -`safeAudit()` lives in `Services/Concerns/AuditsExtensionActions.php` and is used by both `ReservationService` and `ConfigOptionSetupService`. Audit failures emit `Log::warning('extension audit write failed', [...])` so they appear in normal application logs even without a configured exception reporter. - ---- - -## Risk Mitigation - -### Risk 1: Pterodactyl API Changes - -**Probability**: Low -**Impact**: High (breaks availability calculation) - -**Mitigation**: -- Abstract API calls behind interface -- Version check on connection test -- Monitor Pterodactyl changelog - -### Risk 2: Database Deadlocks - -**Probability**: Medium (under high concurrency) -**Impact**: Medium (failed reservations) - -**Mitigation**: -- Transaction retry logic (5 attempts) -- Proper index ordering -- Monitor deadlock frequency in logs - -### Risk 3: Stale Availability Data - -**Probability**: Low (real-time API) -**Impact**: Medium (overselling) - -**Mitigation**: -- Final verification at payment -- No caching of availability -- Reservation system as buffer - -### Risk 4: Frontend JavaScript Conflicts - -**Probability**: Medium -**Impact**: Low (broken sliders, not data loss) - -**Mitigation**: -- Namespace all code (`window.DynamicPterodactyl`) -- No global jQuery modifications -- Graceful degradation (fallback to number inputs) - -### Risk 5: Admin Misconfiguration - -**Probability**: High -**Impact**: Medium (incorrect pricing) - -**Mitigation**: -- Form validation prevents invalid configs -- Preview calculator before saving -- Audit logging of all changes - ---- - -## Deployment Checklist - -### Pre-Deployment - -- [ ] All migrations tested on copy of production data -- [ ] Pterodactyl API credentials configured -- [ ] Connection test passes -- [ ] At least one pricing config created -- [ ] Backup database - -### Deployment Steps - -1. Enable maintenance mode -2. Run migrations: `php artisan migrate` -3. Clear caches: `php artisan cache:clear` -4. Register scheduled jobs (cleanup is wired; alerts are not yet scheduled) -5. Disable maintenance mode -6. Verify dashboard loads -7. Test one product with sliders -8. Monitor error logs for 30 minutes - -### Post-Deployment - -- [ ] Verify scheduled jobs running (check `telescope` or logs) -- [ ] Create test reservation, let it expire -- [ ] Complete full purchase flow -- [ ] Check audit log records creation - ---- - -## Rollback Plan - -If critical issues discovered: - -1. **Immediate**: Deactivate all pricing configs (disables sliders) -2. **If needed**: Roll back migration (data loss of configs) - ```bash - php artisan migrate:rollback --step=4 - ``` -3. **Emergency**: Remove extension folder entirely - -Data in `ptero_resource_reservations` is ephemeral and can be safely dropped. - -## Scheduler wiring status - -Expired-reservation cleanup and `AlertService::checkCapacityAlerts()` are both scheduled in `DynamicPterodactyl.php::boot()`. Cleanup runs every minute; capacity checks run every five minutes with `withoutOverlapping()`. - -## Capacity Alerts + Reservation Observability (dp-12) - -`AlertService::checkCapacityAlerts()` is scheduled every 5 minutes in `DynamicPterodactyl.php::boot()`. For each active `ptero_alert_configs` row it: (1) respects `cooldown_minutes` via `last_notification_at`, (2) reads live utilization via `ResourceCalculationService`, (3) dispatches to email (all admins with `role_id`) and/or webhook, (4) writes one `capacity_alert_sent` audit row summarising channels + severity + breached resources. - -`ReservationService::{confirm,cancel,cleanupExpired}` write audit rows on successful state transitions. `confirm` / `cancel` are per-reservation. `cleanupExpired` writes one batch row per run with `count`. Token values are stored as `token_prefix` only. - -Both services use the shared `AuditsExtensionActions` trait (dp-13) — audit failure is best-effort and does not abort business logic. - ---- - -## Performance Benchmarks - -Target performance (measure during testing): - -| Operation | Target | Acceptable | -|-----------|--------|------------| -| Availability fetch | < 200ms | < 500ms | -| Price calculation | < 50ms | < 100ms | -| Reservation creation | < 300ms | < 500ms | -| Dashboard load | < 1s | < 2s | -| Slider response | < 100ms | < 200ms | - -If targets not met, profile with Laravel Telescope or Debugbar. +# Implementation and Verification + +## Runtime boundaries + +- Paymenter 1.5.6, Filament 5, Livewire 4. +- Paymenter core owns pricing, cart/order/service persistence, and the built-in Pterodactyl provisioner. +- Dynamic Pterodactyl owns capacity reads, node selection, reservation identity, and lifecycle validation. +- Pterodactyl owns actual server allocation after a successful create. + +## Required cross-repository changes + +The Paymenter companion branch must include: + +- transactional cart add/edit operations; +- atomic login ownership transfer; +- fail-closed checkout refresh and service binding; +- correct `ServiceConfig.slider_value` serialization; +- Pterodactyl `createServer()` begin/complete/fail integration; +- exact reserved-node and resource overrides; +- removal of browser reservation JavaScript. + +The extension branch must include: + +- checkout identity and provisioning migrations; +- `ReservationConfigurationService`; +- server-owned cart listeners; +- provisioning lifecycle methods; +- lowercase option creation/backfill; +- non-authoritative CPU semantics. + +Deploy the Paymenter 1.5.6 baseline and extension migrations together. Migrating the extension without the companion core leaves no caller for service binding/provisioning consumption. + +## Verification matrix + +| Area | Required proof | +|---|---| +| Upgrade | Paymenter reports 1.5.6 dependency versions | +| Cart | reservation failure rolls back create and edit | +| Identity | resource, plan, location, quantity, currency, or price change changes fingerprint | +| Guest | cart owner and pending holds transfer atomically | +| Checkout | missing, expired, foreign, or mismatched hold rolls back order/service | +| Payment delay | hold expiry extends to invoice due time | +| Concurrency | duplicate cart hold and duplicate provisioning worker are rejected | +| Node binding | outbound Pterodactyl request uses the stored node and limits | +| Retry | existing external server consumes a pending row idempotently | +| Serialization | slider value reaches lowercase service properties and `getServiceProperties()` | +| CPU | changing CPU never rejects a node solely on fabricated capacity | + +Run the Paymenter PHPUnit suite, the extension PHPUnit suite against a dedicated test database, frontend lint/build, and migration up/down checks. The extension test bootstrap must retain its test-database guard. + +## Operational checks + +After deployment: + +1. Run migrations. +2. Verify legacy pending token-flow rows were cancelled with the migration note. +3. Confirm all configured resource/location option keys are lowercase. +4. Inspect one guest-login checkout through paid provisioning. +5. Verify reservation `node_id` equals the created Pterodactyl server node. +6. Verify confirmed rows have `consumed_at` and no active provisioning lease. diff --git a/AGENTS.md b/AGENTS.md index c393314..e5034ff 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,19 +6,19 @@ ## OVERVIEW -Nested Paymenter `Other` extension that complements the built-in Pterodactyl provisioner. It owns real-time capacity reads, short-lived reservations, lifecycle hooks, and Filament administration; Paymenter core remains the slider-pricing authority and the built-in server extension remains the provisioning authority. +Nested Paymenter `Other` extension that complements the built-in Pterodactyl provisioner. It owns real-time capacity reads, server-owned reservations, lifecycle validation, and Filament administration; Paymenter core remains the slider-pricing authority and the built-in server extension remains the provisioning authority. ## STRUCTURE ```text DynamicPterodactyl/ ├── DynamicPterodactyl.php # boot, install/uninstall, policy, listeners, schedules -├── Admin/ # Filament 4 pages/resources; see Admin/AGENTS.md -├── Http/ # customer/admin API controllers, request, middleware -├── Listeners/ # cart, invoice, and service lifecycle adapters +├── Admin/ # Filament 5 pages/resources; see Admin/AGENTS.md +├── Http/ # aggregate customer and raw admin APIs +├── Listeners/ # transactional cart lifecycle adapters ├── Services/ # reservation, capacity, alert, setup, audit core ├── Models/ # 4 ptero_* models plus AlertConfig observer -├── database/migrations/ # 8 migrations, including retired pricing-table drop +├── database/migrations/ # 10 migrations, including checkout identity and key normalization ├── resources/views/admin/ # 1:1 Blade views for standalone admin pages ├── routes/api.php # required from boot(); /api/dynamic-pterodactyl/* ├── tests/ # isolated harness; see tests/AGENTS.md @@ -32,8 +32,8 @@ DynamicPterodactyl/ | Extension lifecycle / schedules | `DynamicPterodactyl.php` | cleanup every minute; alerts every five minutes | | Reservation state changes | `Services/ReservationService.php` | `Listeners/`, `Models/ResourceReservation.php` | | Capacity / node choice | `Services/ResourceCalculationService.php`, `Services/NodeSelectionService.php` | `08-ALGORITHMS.md` | -| Checkout/payment reconciliation | `Listeners/CartItemCreatedListener.php`, `Listeners/InvoicePaidListener.php` | `04-EVENTS.md` | -| Live API surface | `routes/api.php`, `Http/Controllers/Api/` | code outranks retired endpoints in `03-API.md` | +| Checkout/provisioning reconciliation | `Services/ReservationService.php`, companion Pterodactyl `createServer()` | `04-EVENTS.md` | +| Live API surface | `routes/api.php`, `Http/Controllers/Api/` | `03-API.md` | | Core slider metadata / price preview | `Services/SliderConfigReaderService.php`, `Http/Controllers/Api/PricingController.php` | core `Plan` and `ConfigOption` methods own math | | Admin pages and actions | `Admin/AGENTS.md` | `resources/views/admin/` | | Tables / casts / lifecycle values | `Models/`, `database/migrations/` | `DECISIONS.md` before stale schema prose | @@ -48,7 +48,8 @@ Caller counts are CodeGraph static counts; Laravel events, container resolution, |---|---|---|---:|---| | `DynamicPterodactyl::boot()` | method | `DynamicPterodactyl.php` | runtime | route, policy, observer, listener, schedule root | | `ResourceCalculationService` | class | `Services/ResourceCalculationService.php` | 41 | uncached panel reads and cluster capacity snapshots | -| `ReservationService` | class | `Services/ReservationService.php` | 26 | reservation state machine, locking, idempotency, audit | +| `ReservationService` | class | `Services/ReservationService.php` | cross-layer | cart, login, checkout, and provisioning state machine | +| `ReservationConfigurationService` | class | `Services/ReservationConfigurationService.php` | cross-layer | canonical payload and fingerprint authority | | `AlertService` | class | `Services/AlertService.php` | 14 | threshold checks, delivery, shortfall notifications | | `NodeSelectionService` | class | `Services/NodeSelectionService.php` | 11 | best-fit scoring over current capacity | | `SliderConfigReaderService` | class | `Services/SliderConfigReaderService.php` | 5 | native `dynamic_slider` metadata reader | @@ -60,12 +61,13 @@ Caller counts are CodeGraph static counts; Laravel events, container resolution, - Tables use `ptero_*`; memory/disk use MB, CPU uses percent, money uses `decimal(10,2)`, JSON keys use `snake_case`. - Reservation lifecycle is `pending -> confirmed | expired | cancelled`; `released` is retired. -- Active retries use `idempotency_key`; reservation writes use transactions, `lockForUpdate()`, and deadlock retry. -- Audit payloads store `token_prefix`, never a full reservation token; audit writes are best-effort around primary state changes. +- One pending hold is keyed by `cart_item_id`; reservation writes use transactions, `lockForUpdate()`, and deadlock retry. +- Tokens are internal/admin-only and never appear in browser, cart, service, URL, or audit state. - Controllers validate/authorize then delegate. Customer responses expose aggregate capacity; raw node data is admin-only. -- Route budgets are explicit: availability/pricing/admin `30/min`, reservations `10/min`. -- Invoice-paid confirmation must re-check live availability before `ReservationService::confirm()` and notify on drift/shortfall. -- Treat current code plus `DECISIONS.md` as authoritative. `README.md`, `CLAUDE.md`, and numbered specs retain some retired names and endpoints. +- Route budgets are explicit: availability/pricing/admin `30/min`; there is no customer reservation route. +- Provisioning must call `beginProvisioning()` and `completeProvisioning()` around the external create request. +- CPU is never treated as hard node capacity without an external authoritative inventory. +- Treat current code plus `DECISIONS.md` as authoritative. - Record live work in `PROGRESS.md`; record newly settled architecture in `DECISIONS.md`. ## ANTI-PATTERNS (THIS PROJECT) @@ -75,14 +77,14 @@ Caller counts are CodeGraph static counts; Laravel events, container resolution, - Do not cache Pterodactyl responses or snapshots; availability is a real-time contract. - Do not expose node-level capacity on customer routes. - Do not add a local `composer.json` or frontend bundle; the outer app supplies autoloading and native sliders. -- Do not copy Filament v3 APIs into this Filament 4 codebase. +- Do not copy legacy Filament v3/v4 APIs into this Filament 5 codebase. - Do not introduce `released`, `base_plus_addon`, full-token audit fields, or retired API endpoints. - Do not commit from the outer Paymenter worktree; this directory is its own git checkout. ## UNIQUE STYLES - Routes are loaded by `boot()` rather than extension-local framework discovery. -- Four Paymenter events adapt cart/invoice/service lifecycle into the reservation service. +- Cart created/updated/deleting events adapt cart lifecycle into the reservation service; provisioning is a direct companion-core integration. - Schedules are named inline closures in `boot()`; there are no local Job/Command classes. - Filament resources perform actions through services; standalone pages own 1:1 namespaced Blade views. - Pricing preview calls core `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` directly. diff --git a/Admin/AGENTS.md b/Admin/AGENTS.md index f1b2acb..c02b60f 100644 --- a/Admin/AGENTS.md +++ b/Admin/AGENTS.md @@ -2,7 +2,7 @@ ## OVERVIEW -Filament 4 administration surface for Dynamic Pterodactyl. Standalone `Page` classes own dashboard-style screens and bind to 1:1 Blade views; `Resource` classes own model tables/forms and delegate state-changing actions to services. +Filament 5 administration surface for Dynamic Pterodactyl. Standalone `Page` classes own dashboard-style screens and bind to 1:1 Blade views; `Resource` classes own model tables/forms and delegate state-changing actions to services. ## STRUCTURE @@ -34,7 +34,7 @@ Paired views live outside this directory at `../resources/views/admin/`. - Standalone screens extend `Filament\Pages\Page`; resources extend `Filament\Resources\Resource` and register nested page classes through `getPages()`. - Page views are explicitly namespaced: `dynamic-pterodactyl::admin.dashboard`, `setup-wizard`, `node-monitoring`, and `audit-log`; keep PHP page names and Blade filenames paired 1:1. - Resource page classes stay depth-four under `Resources//Pages/` and only point `protected static string $resource` back to the resource unless header actions are needed. -- Use Filament 4 APIs: `Schema $schema`, schema layouts from `Filament\Schemas\Components\*`, inputs from `Filament\Forms\Components\*`, table `recordActions()`, and top-level `Filament\Actions\*` imports. +- Use Filament 5 APIs: `Schema $schema`, schema layouts from `Filament\Schemas\Components\*`, inputs from `Filament\Forms\Components\*`, table `recordActions()`, and top-level `Filament\Actions\*` imports. - `SetupWizard` may be large, but persistence belongs in `ConfigOptionSetupService::createDynamicSliderOptions()`; the page gathers state, validates wizard flow, warns on existing options, and reports setup results. - `ReservationResource` is not a create surface: `canCreate()` returns `false`; extend/cancel/cleanup actions call `ReservationService` with the authenticated actor. - `AlertConfigResource` owns CRUD form/table composition; test notifications call `AlertService::sendTestNotification()`. @@ -48,4 +48,4 @@ Paired views live outside this directory at `../resources/views/admin/`. - Do not make reservations manually creatable from Filament. - Do not bypass `ConfigOptionSetupService` from the setup wizard to write core config options inline. - Do not treat `AlertConfigResource` saves as UI-only changes; observer and alert-service side effects are part of the contract. -- Do not mix Filament v3 resource APIs such as legacy table actions into these Filament 4 resources. +- Do not mix legacy Filament v3/v4 resource APIs into these Filament 5 resources. diff --git a/Admin/Pages/Dashboard.php b/Admin/Pages/Dashboard.php index b6f18f4..f709fe3 100644 --- a/Admin/Pages/Dashboard.php +++ b/Admin/Pages/Dashboard.php @@ -92,7 +92,7 @@ private function buildLocationCapacity(array $snapshot, int $locationId): array { $locationSnapshot = $snapshot['by_location'][$locationId] ?? [ 'nodes' => [], - 'totals' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], + 'totals' => ['memory' => 0, 'cpu' => null, 'disk' => 0], 'allocated' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], ]; @@ -106,7 +106,7 @@ private function buildLocationCapacity(array $snapshot, int $locationId): array 'nodes' => $nodes, 'max_available' => [ 'memory' => \collect($nodes)->max('available.memory') ?? 0, - 'cpu' => \collect($nodes)->max('available.cpu') ?? 0, + 'cpu' => null, 'disk' => \collect($nodes)->max('available.disk') ?? 0, ], 'total_capacity' => $locationSnapshot['totals'], diff --git a/Admin/Pages/NodeMonitoring.php b/Admin/Pages/NodeMonitoring.php index 91c1078..cc295cf 100644 --- a/Admin/Pages/NodeMonitoring.php +++ b/Admin/Pages/NodeMonitoring.php @@ -32,7 +32,7 @@ public function getViewData(): array foreach ($snapshot['locations'] as $location) { $locationSnapshot = $snapshot['by_location'][$location['id']] ?? [ 'nodes' => [], - 'totals' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], + 'totals' => ['memory' => 0, 'cpu' => null, 'disk' => 0], 'allocated' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], ]; diff --git a/CHANGELOG.md b/CHANGELOG.md index 812e654..3360152 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,19 @@ Milestone and release notes. For day-to-day progress, see PROGRESS.md. ## [Unreleased] ### Added +- Server-owned reservation identity covering cart, purchase, node, resource, pricing, and formula snapshots. +- Atomic guest ownership transfer, service binding, panel-identity checks, provisioning leases, retry reconciliation, and consume-on-create lifecycle. +- Migration of legacy uppercase resource keys and persisted `ServiceConfig.slider_value` support in the companion core. - Scheduled `AlertService::checkCapacityAlerts()` every 5 minutes via `DynamicPterodactyl.php::boot()` (dp-12). - `Notifications/CapacityAlertNotification` mail notification for capacity threshold breaches (dp-12). - Audit trail for capacity alert dispatch and reservation state transitions (`confirm`, `cancel`, `cleanupExpired`) using the shared `AuditsExtensionActions` trait (dp-12). - Reservation create endpoint now supports `Idempotency-Key` / `idempotency_key` dedupe with active-reservation reuse semantics. ### Changed +- Rebased the companion Paymenter implementation onto 1.5.6 / Filament 5 / Livewire 4. +- Reservation creation moved from the browser and public API to transactional cart create/update listeners. +- Pterodactyl provisioning now overrides the actual `node`, `location`, `memory`, `cpu`, and `disk` fields from the bound hold. +- CPU availability is explicitly non-authoritative; memory and disk are the hard inventory dimensions. - (dp-11) Authorization hardened for reservations: `StoreReservationRequest::authorize()` now verifies cart-item ownership; `ReservationController::get|cancel|extend` now use `ResourceReservationPolicy` (Filament panel access via `User::canAccessPanel()`) instead of the broken `is_admin` check; `ReservationService::cancel|extend|confirm` accept an optional `?User $actor` and authorize via the policy when supplied (defence-in-depth). - (dp-11) Surface reduced: deleted retired `PricingController::validate` (410 stub from dp-09) and `ReservationService::getAll()` (no callers — `queryAll()` is the live path); narrowed five internal helpers (`presentReservation`, `getActiveByIdempotencyKey`, `calculateNodeAvailability`, `createResourceOption`, `createLocationOption`) to `private`. - (dp-10) The extension-consumed `dynamic_slider` component now exposes the full WAI-ARIA APG attribute set, keyboard PageUp/Down/Home/End support, loading/error UI states, and a 44px touch target. No extension code changes required — these are fork-side core improvements. @@ -22,6 +29,10 @@ Milestone and release notes. For day-to-day progress, see PROGRESS.md. - Pricing preview now delegates to Paymenter core (`Plan::dynamicSliderBasePrice()` + `ConfigOption::calculateDynamicPriceDelta()`), `PricingCalculatorService` was renamed to `SliderConfigReaderService`, and `PricingConfigValidator` was retired in favor of core `DynamicSliderPricingRule`. ### Fixed +- Removed the competing browser and cart-listener holds, stale slider idempotency reuse, URL/session token exposure, and fail-open checkout paths. +- Holds remain pending through payment and external provisioning, closing the confirmed-before-server capacity gap. +- Guest reservations are transferred to the authenticated customer instead of failing owner checks at checkout. +- Dynamic option keys use the lowercase fields read by the built-in Pterodactyl provisioner. - Capacity-alert email delivery: replaced `Log::info('email would be sent')` stub in `AlertService::sendNotifications()` with real admin-user fan-out (dp-12). - Payment-time reservation confirmation now excludes the reservation itself from pending-capacity math, so exact-fit purchases can confirm successfully. - Reservation create requests now enforce product slider bounds and reject unconfigured products instead of persisting arbitrary resource selections. diff --git a/DECISIONS.md b/DECISIONS.md index fca4bc1..983de88 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -197,6 +197,36 @@ Architectural decisions with rationale. Check here before re-debating a settled --- +## Decisions locked 2026-07-25 + +These decisions supersede the earlier Filament 4, browser-reservation, invoice-confirmation, and CPU-weighted node-selection decisions. + +### 12. Paymenter baseline + +The companion fork targets Paymenter 1.5.6, Filament 5, and Livewire 4. The previous 1.4.7 baseline is release-blocking because it predates applicable security fixes. + +### 13. Reservation ownership + +Exactly one server-owned reservation exists per dynamic cart item. Customer reservation endpoints, bearer tokens, session storage, Livewire token state, and browser idempotency are retired. + +### 14. Immutable checkout identity + +Every new hold stores a canonical payload and SHA-256 fingerprint covering customer, cart, Paymenter server extension, hashed panel identity, product, plan, location, node, resources, quantity, currency, calculated price, pricing version, formula version, and option metadata. The capacity reader and provisioner must resolve to the same normalized panel URL. Guest login atomically updates both row ownership and the customer identity embedded in that payload. + +### 15. Provisioning is the consume boundary + +Checkout binds and extends a pending hold; it does not confirm it. The built-in Pterodactyl provisioner leases the row, overrides the actual node/resource settings, and marks it confirmed only after the external server create succeeds. + +### 16. CPU is not hard Pterodactyl inventory + +Without an external authoritative inventory, CPU is a fingerprinted/provisioned server limit only. Node eligibility and scoring use memory and disk. Availability explicitly reports `cpu_capacity_enforced = false`. + +### 17. Normalized provisioner keys + +Dynamic option environment variables are lowercase `memory`, `cpu`, `disk`, and `location`. This is the casing consumed by the built-in Pterodactyl extension. The normalization migration is intentionally irreversible. + +--- + ## How to Propose a Change If you believe a decision should be reconsidered: diff --git a/DynamicPterodactyl.php b/DynamicPterodactyl.php index d94042a..b63852f 100644 --- a/DynamicPterodactyl.php +++ b/DynamicPterodactyl.php @@ -5,9 +5,8 @@ use App\Attributes\ExtensionMeta; use App\Classes\Extension\Extension; use App\Events\CartItem\Created as CartItemCreated; -use App\Events\CartItem\Deleted as CartItemDeleted; -use App\Events\Invoice\Paid as InvoicePaid; -use App\Events\Service\Created as ServiceCreated; +use App\Events\CartItem\Deleting as CartItemDeleting; +use App\Events\CartItem\Updated as CartItemUpdated; use App\Helpers\ExtensionHelper; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Gate; @@ -15,8 +14,6 @@ use Illuminate\Support\Facades\View; use Paymenter\Extensions\Others\DynamicPterodactyl\Listeners\CartItemCreatedListener; use Paymenter\Extensions\Others\DynamicPterodactyl\Listeners\CartItemDeletedListener; -use Paymenter\Extensions\Others\DynamicPterodactyl\Listeners\InvoicePaidListener; -use Paymenter\Extensions\Others\DynamicPterodactyl\Listeners\ServiceCreatedListener; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\ResourceReservation; use Paymenter\Extensions\Others\DynamicPterodactyl\Policies\ResourceReservationPolicy; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AlertService; @@ -25,7 +22,7 @@ #[ExtensionMeta( name: 'Dynamic Pterodactyl', description: 'Dynamic resource sliders (RAM/CPU/Disk), real-time availability, and 15-min reservations for Pterodactyl products.', - version: '3.1.0', + version: '4.0.0', author: 'Paymenter', url: '', icon: 'heroicon-o-server', @@ -134,13 +131,10 @@ private function registerEventListeners(): void // Cart item created - create resource reservation Event::listen(CartItemCreated::class, CartItemCreatedListener::class); - // Cart item deleted - cancel reservation - Event::listen(CartItemDeleted::class, CartItemDeletedListener::class); + // Cart item edited - replace or refresh its resource reservation + Event::listen(CartItemUpdated::class, CartItemCreatedListener::class); - // Invoice paid - confirm reservation - Event::listen(InvoicePaid::class, InvoicePaidListener::class); - - // Service created - log linkage (tracking only) - Event::listen(ServiceCreated::class, ServiceCreatedListener::class); + // Cancel before deletion while the cart-item relationship still exists + Event::listen(CartItemDeleting::class, CartItemDeletedListener::class); } } diff --git a/Http/Controllers/Api/Admin/AdminCapacityController.php b/Http/Controllers/Api/Admin/AdminCapacityController.php index a369a82..ee0fae9 100644 --- a/Http/Controllers/Api/Admin/AdminCapacityController.php +++ b/Http/Controllers/Api/Admin/AdminCapacityController.php @@ -23,7 +23,7 @@ public function summary(): JsonResponse foreach ($snapshot['locations'] as $location) { $locationSnapshot = $snapshot['by_location'][$location['id']] ?? [ 'nodes' => [], - 'totals' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], + 'totals' => ['memory' => 0, 'cpu' => null, 'disk' => 0], 'allocated' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], ]; diff --git a/Http/Controllers/Api/AvailabilityController.php b/Http/Controllers/Api/AvailabilityController.php index 1c53217..33cb8e5 100644 --- a/Http/Controllers/Api/AvailabilityController.php +++ b/Http/Controllers/Api/AvailabilityController.php @@ -26,7 +26,7 @@ public function getByLocation(int $locationId): JsonResponse $maxAvailable = $this->nodeService->getMaxAvailable($locationId, $locationData); $resourceCapacity = [ 'memory' => $maxAvailable['memory'] > 0, - 'cpu' => $maxAvailable['cpu'] > 0, + 'cpu' => null, 'disk' => $maxAvailable['disk'] > 0, ]; @@ -38,8 +38,9 @@ public function getByLocation(int $locationId): JsonResponse 'max_cpu' => $maxAvailable['cpu'], 'max_disk' => $maxAvailable['disk'], 'node_count' => count($locationData['nodes']), - 'has_capacity' => $resourceCapacity['memory'] && $resourceCapacity['cpu'] && $resourceCapacity['disk'], + 'has_capacity' => $resourceCapacity['memory'] && $resourceCapacity['disk'], 'resource_capacity' => $resourceCapacity, + 'cpu_capacity_enforced' => false, ], ]); } catch (\Throwable $e) { diff --git a/Http/Controllers/Api/ReservationController.php b/Http/Controllers/Api/ReservationController.php deleted file mode 100644 index af76ae9..0000000 --- a/Http/Controllers/Api/ReservationController.php +++ /dev/null @@ -1,137 +0,0 @@ -reservationService = $reservationService; - } - - public function create(StoreReservationRequest $request): JsonResponse - { - $user = $request->user(); - $validated = $request->validated(); - // Guests reach this endpoint before login, so user_id intentionally stays null. - $resources = [ - 'memory' => (int) ($validated['memory'] ?? 0), - 'cpu' => (int) ($validated['cpu'] ?? 0), - 'disk' => (int) ($validated['disk'] ?? 0), - ]; - - try { - $reservation = $this->reservationService->create( - productId: $validated['product_id'], - locationId: $validated['location_id'], - resources: $resources, - cartItemId: $validated['cart_item_id'] ?? null, - userId: $user?->id, - idempotencyKey: $validated['idempotency_key'] ?? null, - ); - - return response()->json([ - 'success' => true, - 'data' => $reservation, - ]); - } catch (\RuntimeException $e) { - return response()->json([ - 'success' => false, - 'message' => $e->getMessage(), - ], 422); - } catch (\Exception $e) { - return response()->json([ - 'success' => false, - 'message' => 'Failed to create reservation', - ], 500); - } - } - - public function get(string $token): JsonResponse - { - $reservation = ResourceReservation::query()->where('token', $token)->first(); - - if (! $reservation) { - return response()->json([ - 'success' => false, - 'message' => 'Reservation not found', - ], 404); - } - - $this->authorize('view', $reservation); - - return response()->json([ - 'success' => true, - 'data' => $reservation, - ]); - } - - public function cancel(Request $request, string $token): JsonResponse - { - $reservation = ResourceReservation::query()->where('token', $token)->first(); - - if (! $reservation) { - return response()->json([ - 'success' => false, - 'message' => 'Reservation not found', - ], 404); - } - - $this->authorize('cancel', $reservation); - - $result = $this->reservationService->cancel($token, null, 'customer', $request->user()); - - return response()->json([ - 'success' => $result, - 'message' => $result ? 'Reservation cancelled' : 'Failed to cancel reservation', - ]); - } - - public function extend(Request $request, string $token): JsonResponse - { - $validated = $request->validate([ - 'minutes' => 'integer|min:1|max:60', - ]); - - $reservation = ResourceReservation::query()->where('token', $token)->first(); - - if (! $reservation) { - return response()->json([ - 'success' => false, - 'message' => 'Reservation not found', - ], 404); - } - - $this->authorize('extend', $reservation); - - $result = $this->reservationService->extend($token, $validated['minutes'] ?? 15, $request->user()); - - if ($result) { - $updated = $this->reservationService->getByToken($token); - - return response()->json([ - 'success' => true, - 'data' => [ - 'expires_at' => $updated->expires_at, - ], - ]); - } - - return response()->json([ - 'success' => false, - 'message' => 'Failed to extend reservation', - ], 500); - } -} diff --git a/Http/Requests/StoreReservationRequest.php b/Http/Requests/StoreReservationRequest.php deleted file mode 100644 index 3e56b87..0000000 --- a/Http/Requests/StoreReservationRequest.php +++ /dev/null @@ -1,162 +0,0 @@ -integer('cart_item_id'); - - if (! $cartItemId) { - return true; - } - - $cartItem = CartItem::query() - ->with('cart') - ->find($cartItemId); - - if (! $cartItem || ! $cartItem->cart) { - return false; - } - - return $cartItem->cart->user_id === $this->user()?->id; - } - - protected function prepareForValidation(): void - { - $this->merge([ - 'idempotency_key' => $this->header('Idempotency-Key', $this->input('idempotency_key')), - ]); - } - - public function rules(): array - { - return [ - 'product_id' => 'required|integer|exists:products,id', - 'location_id' => 'required|integer', - 'memory' => 'sometimes|integer|min:0', - 'cpu' => 'sometimes|integer|min:0', - 'disk' => 'sometimes|integer|min:0', - 'cart_item_id' => 'nullable|integer|exists:cart_items,id', - 'idempotency_key' => ['nullable', 'regex:/^[A-Za-z0-9-]{8,64}$/'], - ]; - } - - public function withValidator($validator): void - { - $validator->after(function ($validator) { - $productId = (int) $this->input('product_id'); - - if ($productId <= 0 || ! Product::query()->whereKey($productId)->exists()) { - return; - } - - $allowedLocationIds = $this->getAllowedLocationIds($productId); - $locationId = (int) $this->input('location_id'); - if ($allowedLocationIds !== [] && ! in_array($locationId, $allowedLocationIds, true)) { - $validator->errors()->add('location_id', 'The selected location is not configured for this product'); - } - - $sliders = $this->getDynamicSliderConfig($productId); - - if ($sliders === []) { - $validator->errors()->add('product_id', 'This product is not configured for dynamic reservations'); - - return; - } - - $providedResources = collect(['memory', 'cpu', 'disk']) - ->filter(fn (string $resource) => $this->exists($resource)) - ->values() - ->all(); - - foreach (array_diff(array_keys($sliders), $providedResources) as $resource) { - $validator->errors()->add($resource, ucfirst($resource) . ' is required for this product'); - } - - foreach (array_diff($providedResources, array_keys($sliders)) as $resource) { - $validator->errors()->add($resource, ucfirst($resource) . ' is not configured for this product'); - } - - foreach ($sliders as $resource => $slider) { - if (! $this->exists($resource) || $validator->errors()->has($resource)) { - continue; - } - - $value = $this->input($resource); - if (! is_numeric($value)) { - continue; - } - - $value = (int) $value; - $min = (int) ($slider['min'] ?? 0); - $max = (int) ($slider['max'] ?? 0); - $step = max(1, (int) ($slider['step'] ?? 1)); - - if ($value < $min || $value > $max) { - $validator->errors()->add($resource, ucfirst($resource) . " must be between {$min} and {$max}"); - - continue; - } - - if (($value - $min) % $step !== 0) { - $validator->errors()->add($resource, ucfirst($resource) . " must increase in steps of {$step}"); - } - } - }); - } - - private function getDynamicSliderConfig(int $productId): array - { - return DB::table('config_options') - ->join('config_option_products', 'config_options.id', '=', 'config_option_products.config_option_id') - ->where('config_option_products.product_id', $productId) - ->where('config_options.type', 'dynamic_slider') - ->whereNull('config_options.parent_id') - ->select(['config_options.name', 'config_options.metadata']) - ->get() - ->mapWithKeys(function ($option) { - $metadata = is_array($option->metadata) - ? $option->metadata - : json_decode($option->metadata ?? '[]', true) ?? []; - - $resourceType = $metadata['resource_type'] ?? strtolower($option->name); - - if (! in_array($resourceType, ['memory', 'cpu', 'disk'], true)) { - return []; - } - - return [$resourceType => $metadata]; - }) - ->all(); - } - - private function getAllowedLocationIds(int $productId): array - { - $product = Product::query()->find($productId); - $setting = $product?->settings() - ->where('key', 'location_ids') - ->value('value'); - - if ($setting === null || $setting === '') { - return []; - } - - $locationIds = is_array($setting) ? $setting : json_decode($setting, true); - if (! is_array($locationIds)) { - return []; - } - - return collect($locationIds) - ->filter(fn ($locationId) => is_numeric($locationId)) - ->map(fn ($locationId) => (int) $locationId) - ->values() - ->all(); - } -} diff --git a/Listeners/CartItemCreatedListener.php b/Listeners/CartItemCreatedListener.php index 94e191b..48a64b6 100644 --- a/Listeners/CartItemCreatedListener.php +++ b/Listeners/CartItemCreatedListener.php @@ -3,171 +3,35 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Listeners; use App\Events\CartItem\Created; -use App\Models\ConfigOption; -use Illuminate\Support\Facades\DB; +use App\Events\CartItem\Updated; use Illuminate\Support\Facades\Log; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationConfigurationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationService; class CartItemCreatedListener { - public function handle(Created $event): void + public function __construct( + private readonly ReservationService $reservationService, + private readonly ReservationConfigurationService $configurationService + ) {} + + public function handle(Created|Updated $event): void { $cartItem = $event->cartItem; - // Check if this product has dynamic_slider config options (Pterodactyl resources) - if (! $this->hasDynamicSliderOptions($cartItem->product_id)) { - return; - } - - // Extract resource values from Paymenter's native config_options array - // config_options format: [{option_id: X, value: Y}, ...] - $resources = $this->extractResourcesFromConfigOptions( - $cartItem->config_options ?? [] - ); - - // Check if required resources exist (at minimum, need memory to proceed) - if (empty($resources)) { - Log::debug('CartItem has no dynamic_slider resources for reservation', [ - 'cart_item_id' => $cartItem->id, - ]); - - return; - } - - // Location is required for reservation - check checkout_config or config_options - $locationId = $this->extractLocationId($cartItem); - if (! $locationId) { - Log::debug('CartItem missing location for reservation', [ - 'cart_item_id' => $cartItem->id, - ]); - + if (! $this->configurationService->requiresReservation($cartItem->product_id)) { return; } - try { - $reservationService = app(ReservationService::class); - - $reservation = $reservationService->create( - productId: $cartItem->product_id, - locationId: (int) $locationId, - resources: [ - 'memory' => (int) ($resources['memory'] ?? 0), - 'cpu' => (int) ($resources['cpu'] ?? 0), - 'disk' => (int) ($resources['disk'] ?? 0), - ], - cartItemId: $cartItem->id, - userId: auth()->id() - ); - - // Store reservation token in checkout_config for later reference - $checkoutConfig = $cartItem->checkout_config ?? []; - $checkoutConfig['_reservation_token'] = $reservation['token']; - $checkoutConfig['_selected_node'] = $reservation['node_id']; - $checkoutConfig['_calculated_price'] = $reservation['pricing']['total']; - - $cartItem->update([ - 'checkout_config' => $checkoutConfig, - ]); - - Log::info('Created resource reservation for cart item', [ - 'cart_item_id' => $cartItem->id, - 'reservation_token' => substr($reservation['token'], 0, 8) . '...', - 'node_id' => $reservation['node_id'], - 'expires_at' => $reservation['expires_at'], - ]); - - } catch (\Exception $e) { - // Log error but don't block the cart operation - // User can still checkout, but without guaranteed resources - Log::error('Failed to create resource reservation', [ - 'cart_item_id' => $cartItem->id, - 'error' => $e->getMessage(), - ]); - } - } - - /** - * Extract resource values from native dynamic_slider config options - * Uses metadata.resource_type to identify memory/cpu/disk sliders - */ - private function extractResourcesFromConfigOptions(array $configOptions): array - { - $resources = []; - - foreach ($configOptions as $opt) { - $optionId = $opt['option_id'] ?? null; - $value = $opt['value'] ?? null; - - if (! $optionId || $value === null) { - continue; - } - - // Get the config option to check its type and metadata - $configOption = ConfigOption::find($optionId); - - if (! $configOption || $configOption->type !== 'dynamic_slider') { - continue; - } - - // Get resource type from metadata (memory, cpu, disk, custom) - $resourceType = $configOption->getMetadata('resource_type'); - - if ($resourceType && in_array($resourceType, ['memory', 'cpu', 'disk'])) { - $resources[$resourceType] = $value; - } - } - - return $resources; - } - - /** - * Extract location ID from cart item (checkout_config or config_options) - */ - private function extractLocationId($cartItem): ?int - { - // First, check checkout_config (extension-provided location selector) - $checkoutConfig = $cartItem->checkout_config ?? []; - if (isset($checkoutConfig['location'])) { - return (int) $checkoutConfig['location']; - } - - // Fall back to config_options (if location is a select/radio type) - foreach ($cartItem->config_options ?? [] as $opt) { - $optionId = $opt['option_id'] ?? null; - $value = $opt['value'] ?? null; - - if (! $optionId) { - continue; - } - - $configOption = ConfigOption::find($optionId); - if ($configOption && strtolower($configOption->name) === 'location') { - // Value might be a child config option ID - get its env_variable (Ptero location ID) - if (is_numeric($value)) { - $pteroLocationId = DB::table('config_options') - ->where('id', $value) - ->value('env_variable'); - - return $pteroLocationId ? (int) $pteroLocationId : (int) $value; - } - - return (int) $value; - } - } - - return null; - } + // Exceptions intentionally bubble into the cart transaction. A dynamic + // product must never be added or updated without an authoritative hold. + $reservation = $this->reservationService->reserveForCartItem($cartItem); - /** - * Check if a product has any dynamic_slider config options - */ - private function hasDynamicSliderOptions(int $productId): bool - { - return DB::table('config_options') - ->join('config_option_products', 'config_options.id', '=', 'config_option_products.config_option_id') - ->where('config_option_products.product_id', $productId) - ->where('config_options.type', 'dynamic_slider') - ->whereNull('config_options.parent_id') - ->exists(); + Log::info('Capacity reserved for cart item', [ + 'cart_item_id' => $cartItem->id, + 'reservation_id' => $reservation['id'], + 'node_id' => $reservation['node_id'], + 'expires_at' => $reservation['expires_at'], + ]); } } diff --git a/Listeners/CartItemDeletedListener.php b/Listeners/CartItemDeletedListener.php index 53b90b0..65ad441 100644 --- a/Listeners/CartItemDeletedListener.php +++ b/Listeners/CartItemDeletedListener.php @@ -2,56 +2,19 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Listeners; -use App\Events\CartItem\Deleted; -use App\Models\Service; +use App\Events\CartItem\Deleting; use Illuminate\Support\Facades\Log; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationService; class CartItemDeletedListener { - public function handle(Deleted $event): void - { - $cartItem = $event->cartItem; - - // Reservation token is stored in checkout_config by CartItemCreatedListener - $checkoutConfig = $cartItem->checkout_config ?? []; - $token = $checkoutConfig['dp_reservation_token'] ?? $checkoutConfig['_reservation_token'] ?? null; - - if (!$token) { - return; - } - - // If a Service already carries this reservation token, the cart item was - // deleted as part of a successful checkout. Paymenter core (Cart::checkout) - // copies checkout_config into Service::properties, commits, then clears the - // cart — all BEFORE Invoice\Paid fires. Cancelling here would race-cancel a - // reservation that InvoicePaidListener is about to confirm. Leave it pending. - $serviceExists = Service::whereHas('properties', function ($q) use ($token) { - $q->where('key', '_reservation_token')->where('value', $token); - })->exists(); - - if ($serviceExists) { - Log::debug('Skipping reservation cancel: cart item consumed by checkout', [ - 'cart_item_id' => $cartItem->id, - 'reservation_token' => substr($token, 0, 8) . '...', - ]); - - return; - } + public function __construct(private readonly ReservationService $reservationService) {} - try { - $reservationService = app(ReservationService::class); - // System event: cart cleanup may happen outside an authenticated HTTP request. - $reservationService->cancel($token, null, 'cart_deleted', null); - - Log::info('Cancelled reservation for deleted cart item', [ - 'cart_item_id' => $cartItem->id, - 'reservation_token' => substr($token, 0, 8) . '...', - ]); - } catch (\Exception $e) { - Log::error('Failed to cancel reservation', [ - 'token' => substr($token, 0, 8) . '...', - 'error' => $e->getMessage(), + public function handle(Deleting $event): void + { + if ($this->reservationService->cancelForCartItem($event->cartItem->id)) { + Log::info('Cancelled capacity reservation for removed cart item', [ + 'cart_item_id' => $event->cartItem->id, ]); } } diff --git a/Listeners/InvoicePaidListener.php b/Listeners/InvoicePaidListener.php deleted file mode 100644 index 415dca2..0000000 --- a/Listeners/InvoicePaidListener.php +++ /dev/null @@ -1,135 +0,0 @@ -invoice; - - foreach ($invoice->items as $item) { - if ($item->reference_type !== Service::class) { - continue; - } - - $service = $item->reference; - if (!$service) { - continue; - } - - $reservationToken = $service->properties() - ->where('key', '_reservation_token') - ->value('value'); - - if (!$reservationToken) { - continue; - } - - try { - $reservationService = app(ReservationService::class); - $resourceService = app(ResourceCalculationService::class); - $alertService = app(AlertService::class); - - $reservation = $reservationService->getByToken($reservationToken); - - if (!$reservation) { - Log::warning('Reservation not found for paid invoice', [ - 'service_id' => $service->id, - 'invoice_id' => $invoice->id, - ]); - - continue; - } - - $snapshot = [ - 'memory' => $reservation->memory, - 'cpu' => $reservation->cpu, - 'disk' => $reservation->disk, - ]; - - // CRITICAL: Final availability verification - $available = $resourceService->verifyAvailability( - $reservation->node_id, - $snapshot, - $reservationToken, - ); - - if (!$available) { - Log::error('Resources no longer available for paid service', [ - 'service_id' => $service->id, - 'node_id' => $reservation->node_id, - 'memory' => $reservation->memory, - 'cpu' => $reservation->cpu, - 'disk' => $reservation->disk, - ]); - - try { - $alertService->notifyShortfall( - serviceId: $service->id, - invoiceId: $invoice->id, - snapshot: $snapshot, - reason: 'insufficient_resources', - ); - } catch (\Throwable $e) { - Log::error('Shortfall notification delivery failed', [ - 'service_id' => $service->id, - 'reason' => 'insufficient_resources', - 'error' => $e->getMessage(), - ]); - } - - continue; - } - - // Confirm the reservation. Returns false if no pending row matched — - // meaning the reservation was already cancelled or expired between - // verifyAvailability() and this call (state drift). - // System event: invoice settlement runs without an authenticated actor. - $confirmed = $reservationService->confirm($reservationToken, $service->id, null); - - if ($confirmed) { - Log::info('Confirmed reservation for paid service', [ - 'service_id' => $service->id, - 'node_id' => $reservation->node_id, - ]); - } else { - $current = $reservationService->getByToken($reservationToken); - Log::warning('Reservation could not be confirmed (state drift)', [ - 'service_id' => $service->id, - 'reservation_id' => $reservation->id, - 'current_status' => $current?->status, - ]); - - try { - $alertService->notifyShortfall( - serviceId: $service->id, - invoiceId: $invoice->id, - snapshot: $snapshot, - reason: 'state_drift:' . ($current?->status ?? 'unknown'), - ); - } catch (\Throwable $e) { - Log::error('Shortfall notification delivery failed', [ - 'service_id' => $service->id, - 'reason' => 'state_drift', - 'error' => $e->getMessage(), - ]); - } - } - - } catch (\Exception $e) { - Log::error('Invoice reservation processing failed', [ - 'service_id' => $service->id, - 'error' => $e->getMessage(), - ]); - } - } - } -} diff --git a/Listeners/ServiceCreatedListener.php b/Listeners/ServiceCreatedListener.php deleted file mode 100644 index 05b0311..0000000 --- a/Listeners/ServiceCreatedListener.php +++ /dev/null @@ -1,32 +0,0 @@ -service; - - // Get reservation token from service properties (morphMany relationship) - $reservationToken = $service->properties() - ->where('key', '_reservation_token') - ->value('value'); - - if (! $reservationToken) { - return; - } - - Log::info('Service created with reservation', [ - 'service_id' => $service->id, - 'reservation_token' => substr($reservationToken, 0, 8) . '...', - 'product_id' => $service->product_id, - ]); - - // The reservation should already be confirmed by InvoicePaidListener - // This is just for logging/tracking purposes - } -} diff --git a/Models/ResourceReservation.php b/Models/ResourceReservation.php index f0fa1ee..6c11fda 100644 --- a/Models/ResourceReservation.php +++ b/Models/ResourceReservation.php @@ -15,8 +15,19 @@ class ResourceReservation extends Model 'token', 'idempotency_key', 'cart_item_id', + 'cart_id', + 'server_extension_id', + 'panel_identity', 'service_id', 'user_id', + 'product_id', + 'plan_id', + 'quantity', + 'currency_code', + 'configuration_fingerprint', + 'configuration_payload', + 'pricing_version', + 'formula_version', 'node_id', 'location_id', 'memory', @@ -27,11 +38,18 @@ class ResourceReservation extends Model 'status', 'admin_notes', 'expires_at', + 'provisioning_started_at', + 'provisioning_lease_id', + 'consumed_at', + 'last_provisioning_error', ]; protected $casts = [ 'pricing_breakdown' => 'array', + 'configuration_payload' => 'array', 'expires_at' => 'datetime', + 'provisioning_started_at' => 'datetime', + 'consumed_at' => 'datetime', 'calculated_price' => 'decimal:2', ]; diff --git a/README.md b/README.md index f89a887..cbadf68 100644 --- a/README.md +++ b/README.md @@ -1,154 +1,54 @@ -# Dynamic Resource Sliders for Pterodactyl Integration +# Dynamic Pterodactyl -**Version:** 3.1.0 -**Status:** Final Design -**Pattern:** Companion Extension +Companion extension for Paymenter 1.5.6 that adds native RAM/CPU/disk sliders, live memory/disk capacity holds, deterministic node selection, and Filament 5 administration to the built-in Pterodactyl server extension. ---- +## Ownership -## Quick Summary +| Concern | Authority | +|---|---| +| Slider UI and price calculation | Paymenter core | +| Checkout capacity identity and node selection | Dynamic Pterodactyl | +| Server creation and actual allocation | Built-in Pterodactyl extension | -Enable Paymenter customers to select exact RAM, CPU, and Disk amounts using sliders during checkout for Pterodactyl game servers, with real-time availability tracking and automatic node selection. - ---- - -## Architecture Diagram - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ Product Configuration │ -├─────────────────────────────────────────────────────────────────────┤ -│ Server Extension: Pterodactyl (built-in, unchanged) │ -│ └── Handles: Server creation, ports, users │ -├─────────────────────────────────────────────────────────────────────┤ -│ Configurable Options: │ -│ ├── memory (Number) ─────┐ │ -│ ├── cpu (Number) ────────┼── Flow to createServer() │ -│ ├── disk (Number) ───────┘ │ -│ └── location_id (Select) ── Triggers availability fetch │ -├─────────────────────────────────────────────────────────────────────┤ -│ DynamicPterodactyl (Companion Extension): │ -│ ├── Real-time availability API │ -│ ├── Resource reservation system (15-min TTL) │ -│ ├── Slider config reads via SliderConfigReaderService │ -│ ├── No custom frontend assets; native core slider UI │ -│ ├── Admin dashboard & configuration UI │ -│ └── Event hooks for cart/invoice/service lifecycle │ -└─────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## Why Companion Pattern? - -| Factor | Standalone | Companion ✓ | -|--------|------------|-------------| -| Lines of code | ~800+ | ~400 | -| Pterodactyl provisioning | Must reimplement | Reuses existing | -| Upstream bug fixes | Manual port | Automatic | -| If extension fails | Product broken | Graceful degradation | - ---- - -## Document Index - -| Document | Purpose | Read When... | -|----------|---------|--------------| -| [01-DATABASE.md](01-DATABASE.md) | Schema, migrations, relationships | Setting up tables, understanding data model | -| [02-SERVICES.md](02-SERVICES.md) | Core business logic services | Implementing backend functionality | -| [03-API.md](03-API.md) | REST endpoints, controllers | Building API layer | -| [04-EVENTS.md](04-EVENTS.md) | Cart/invoice event handlers | Integrating with Paymenter lifecycle | -| [05-ADMIN-UI.md](05-ADMIN-UI.md) | Filament dashboard & resources | Building admin interface | -| [06-FRONTEND.md](06-FRONTEND.md) | Native slider architecture, Alpine.js | Implementing customer-facing UI | -| [07-PRICING-MODELS.md](07-PRICING-MODELS.md) | Pricing logic & JSON configs | Understanding/implementing pricing | -| [08-ALGORITHMS.md](08-ALGORITHMS.md) | Node selection, concurrency | Implementing allocation logic | -| [09-IMPLEMENTATION.md](09-IMPLEMENTATION.md) | Roadmap, testing, risks | Planning & project management | - ---- - -## Key Technical Decisions - -### Real-Time API (No Caching) -- Query Pterodactyl API directly at checkout time -- Eliminates cache staleness issues -- Proven by PteroSync WHMCS module in production - -### Reservation System -- 15-minute TTL holds resources during checkout -- Pessimistic database locking prevents overselling -- Final verification at payment time - -### Three Pricing Models -1. **Linear** - Simple per-unit (e.g., $0.50/GB RAM) -2. **Tiered** - Volume discounts at breakpoints -3. **Base + Addon** - Included resources + overage charges - -Paymenter core is the pricing authority for `dynamic_slider` options. The fork-only core patches in `dp-core-01` (merged) handle slider pricing at runtime via `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()`. This extension's `SliderConfigReaderService` reads slider config metadata; `PricingConfigValidator` is retired in favour of core `DynamicSliderPricingRule`. - -### Frontend Slider -- Customer-facing sliders use Paymenter core's native `dynamic_slider` component -- Rendering is a native HTML range input managed by Alpine.js in the core theme -- Price updates happen client-side, with Livewire entanglement keeping cart state in sync - ---- - -## File Structure +The browser never owns a reservation. A synchronous cart listener creates one server-owned hold, checkout binds it to the service, and the provisioner consumes it only after Pterodactyl accepts the server. +```mermaid +flowchart TD + A["Native sliders"] --> B["Transactional cart hold"] + B --> C["Service-bound pending hold"] + C --> D["Reserved node and limits"] + D --> E["Pterodactyl server"] + E --> F["Consumed reservation"] ``` -extensions/Others/DynamicPterodactyl/ -├── DynamicPterodactyl.php # Main extension class -├── database/migrations/ # 7 migration files -├── Admin/ -│ ├── Pages/ # Dashboard, Analytics, Settings, etc. -│ └── Resources/ # AlertConfig, Reservation -├── Http/Controllers/ # API and Admin controllers -├── Models/ # Eloquent models -├── resources/views/ # Blade templates -├── routes/ # API and web routes -└── Services/ # Core business logic -``` - ---- - -## Database Tables - -| Table | Purpose | -|-------|---------| -| `ptero_resource_reservations` | Temporary resource holds during checkout | -| `ptero_audit_logs` | Admin action tracking | -| `ptero_alert_configs` | Capacity alert thresholds | - ---- - -## Cross-Reference: Common Tasks - -| Task | Primary Doc | Also See | -|------|-------------|----------| -| Add new pricing model | 07-PRICING-MODELS | 02-SERVICES | -| Fix reservation bug | 02-SERVICES | 08-ALGORITHMS | -| Modify admin dashboard | 05-ADMIN-UI | - | -| Change slider behavior | 06-FRONTEND | 03-API | -| Add new event hook | 04-EVENTS | 02-SERVICES | -| Understand node selection | 08-ALGORITHMS | 02-SERVICES | - ---- - -## Quick Start for Implementation - -1. **Database first**: Follow [01-DATABASE.md](01-DATABASE.md) to create migrations -2. **Services**: Implement services from [02-SERVICES.md](02-SERVICES.md) -3. **API**: Build endpoints per [03-API.md](03-API.md) -4. **Events**: Wire up handlers from [04-EVENTS.md](04-EVENTS.md) -5. **Admin**: Create Filament UI from [05-ADMIN-UI.md](05-ADMIN-UI.md) -6. **Frontend**: Add sliders using [06-FRONTEND.md](06-FRONTEND.md) - ---- - -## Version History -| Version | Date | Changes | -|---------|------|---------| -| 1.0 | Nov 2025 | Initial cached architecture | -| 2.0 | Nov 2025 | Real-time API approach | -| 3.0 | Nov 2025 | Companion Extension pattern | -| 3.1 | Nov 2025 | Comprehensive Admin UI, split documentation | +## Safety properties + +- Paymenter baseline is 1.5.6. +- Cart create/edit and checkout fail closed for dynamic products. +- Guest ownership transfers with the cart in one transaction. +- The immutable fingerprint covers customer, cart, Paymenter server extension, hashed panel identity, product, plan, location, node, resources, quantity, currency, pricing version, and formula version. +- Holds remain pending through payment and external provisioning. +- The actual Pterodactyl request uses the reserved `node`, `memory`, `cpu`, and `disk`. +- Config keys are lowercase and dynamic `ServiceConfig.slider_value` is serialized correctly. +- CPU is a provisioned limit, not fabricated hard node inventory. +- Customer reservation tokens and reservation endpoints do not exist. + +## Documentation + +| Document | Topic | +|---|---| +| [01-DATABASE.md](01-DATABASE.md) | Reservation schema and lifecycle | +| [02-SERVICES.md](02-SERVICES.md) | Service responsibilities | +| [03-API.md](03-API.md) | Live customer/admin routes | +| [04-EVENTS.md](04-EVENTS.md) | Cart, login, checkout, and provisioning flow | +| [05-ADMIN-UI.md](05-ADMIN-UI.md) | Filament admin surfaces | +| [06-FRONTEND.md](06-FRONTEND.md) | Native slider frontend | +| [07-PRICING-MODELS.md](07-PRICING-MODELS.md) | Core-owned pricing models | +| [08-ALGORITHMS.md](08-ALGORITHMS.md) | Capacity and concurrency | +| [09-IMPLEMENTATION.md](09-IMPLEMENTATION.md) | Deployment and verification | + +## Installation boundary + +This extension must be deployed with the companion Paymenter remediation branch. Run the Paymenter and extension migrations together, then execute both test suites against a dedicated test database. + +The extension stores no cached Pterodactyl capacity. Customer responses expose aggregate location signals only; raw node data remains admin-only. diff --git a/Services/ConfigOptionSetupService.php b/Services/ConfigOptionSetupService.php index 61fc310..cc3d20a 100644 --- a/Services/ConfigOptionSetupService.php +++ b/Services/ConfigOptionSetupService.php @@ -87,6 +87,7 @@ private function createResourceOption(int $productId, string $resourceType, arra if ($existingOption) { $existingOption->update([ 'type' => 'dynamic_slider', + 'env_variable' => $resourceType, 'metadata' => $metadata, ]); @@ -96,7 +97,7 @@ private function createResourceOption(int $productId, string $resourceType, arra $option = ConfigOption::create([ 'name' => ucfirst($resourceType), 'type' => 'dynamic_slider', - 'env_variable' => strtoupper($resourceType), + 'env_variable' => $resourceType, 'hidden' => false, 'sort' => match ($resourceType) { 'memory' => 1, @@ -176,11 +177,12 @@ private function createLocationOption(int $productId, array $locations): ConfigO if ($existingLocation) { $locationOption = $existingLocation; + $locationOption->update(['env_variable' => 'location']); } else { $locationOption = ConfigOption::create([ 'name' => 'Location', 'type' => 'select', - 'env_variable' => 'LOCATION', + 'env_variable' => 'location', 'hidden' => false, 'sort' => 0, 'parent_id' => null, diff --git a/Services/NodeSelectionService.php b/Services/NodeSelectionService.php index 09050e5..8d84ec1 100644 --- a/Services/NodeSelectionService.php +++ b/Services/NodeSelectionService.php @@ -14,14 +14,21 @@ public function __construct(ResourceCalculationService $resourceService) /** * Select the best node for given resource requirements * - * Algorithm: Best-fit with headroom weighting - * - Memory: 50% weight (most commonly upgraded) - * - Disk: 35% weight (harder to migrate) - * - CPU: 15% weight (often unlimited/shared) + * Algorithm: memory/disk headroom weighting. + * + * Pterodactyl does not expose authoritative node CPU capacity, so CPU is + * passed through as a server limit but is never treated as hard inventory. */ - public function selectBestNode(int $locationId, array $requirements): ?array + public function selectBestNode( + int $locationId, + array $requirements, + ?string $excludeReservationToken = null + ): ?array { - $locationData = $this->resourceService->getLocationAvailability($locationId); + $locationData = $this->resourceService->getLocationAvailability( + $locationId, + $excludeReservationToken + ); $candidates = []; @@ -35,31 +42,25 @@ public function selectBestNode(int $locationId, array $requirements): ?array if ($node['available']['memory'] < $requirements['memory']) { continue; } - if ($node['available']['cpu'] < $requirements['cpu']) { - continue; - } if ($node['available']['disk'] < $requirements['disk']) { continue; } // Calculate remaining headroom after allocation $remainingMemory = $node['available']['memory'] - $requirements['memory']; - $remainingCpu = $node['available']['cpu'] - $requirements['cpu']; $remainingDisk = $node['available']['disk'] - $requirements['disk']; - // Weighted score: prioritize memory headroom, then disk, then CPU - $memoryScore = ($remainingMemory / max(1, $node['total']['memory'])) * 0.50; - $diskScore = ($remainingDisk / max(1, $node['total']['disk'])) * 0.35; - $cpuScore = ($remainingCpu / max(1, $node['total']['cpu'])) * 0.15; + $memoryScore = ($remainingMemory / max(1, $node['total']['memory'])) * 0.60; + $diskScore = ($remainingDisk / max(1, $node['total']['disk'])) * 0.40; - $score = $memoryScore + $diskScore + $cpuScore; + $score = $memoryScore + $diskScore; $candidates[] = [ 'node' => $node, 'score' => $score, 'remaining' => [ 'memory' => $remainingMemory, - 'cpu' => $remainingCpu, + 'cpu' => null, 'disk' => $remainingDisk, ], ]; diff --git a/Services/ReservationConfigurationService.php b/Services/ReservationConfigurationService.php new file mode 100644 index 0000000..2649152 --- /dev/null +++ b/Services/ReservationConfigurationService.php @@ -0,0 +1,400 @@ +> + * } + */ + public function forCartItem(CartItem $cartItem): array + { + $cartItem->loadMissing([ + 'cart', + 'product.configOptions.children', + 'product.server.settings', + 'plan', + ]); + + if (! $this->requiresReservation($cartItem->product_id)) { + throw new \LogicException('The cart item does not use dynamic resource sliders.'); + } + + if ((int) $cartItem->quantity !== 1) { + throw new DisplayException('Dynamic resource products currently require a quantity of one.'); + } + + $selectedOptions = collect($cartItem->config_options ?? []) + ->keyBy(fn ($option) => (int) data_get($option, 'option_id')); + + $resources = []; + $locationId = null; + $configurationOptions = []; + + foreach ($cartItem->product->configOptions as $option) { + $selection = $selectedOptions->get((int) $option->id); + $value = data_get($selection, 'value'); + $resourceType = strtolower((string) $option->getMetadata('resource_type', '')); + $environmentKey = strtolower((string) ($option->env_variable ?: $option->name)); + + if ($option->type === 'dynamic_slider' && in_array($resourceType, ['memory', 'cpu', 'disk'], true)) { + $minimum = $resourceType === 'cpu' ? 0 : 1; + if ($value === null || ! is_numeric($value) || (float) $value < $minimum) { + throw new DisplayException("A valid {$resourceType} selection is required."); + } + + $resources[$resourceType] = (int) $value; + } + + if ($environmentKey === 'location' || strtolower($option->name) === 'location') { + $locationId = $this->resolveLocationId($option, $value); + } + + $configurationOptions[] = [ + 'id' => (int) $option->id, + 'type' => (string) $option->type, + 'environment_key' => $environmentKey, + 'resource_type' => $resourceType ?: null, + 'value' => is_numeric($value) ? (float) $value : $value, + 'metadata' => $this->canonicalize((array) ($option->metadata ?? [])), + ]; + } + + $staticResources = $this->resolveStaticResources($cartItem); + foreach (['memory', 'cpu', 'disk'] as $requiredResource) { + if (! array_key_exists($requiredResource, $resources)) { + $resources[$requiredResource] = $staticResources[$requiredResource] + ?? throw new DisplayException( + "The {$requiredResource} resource is missing from both the slider and product settings." + ); + } + } + + $locationId ??= $this->resolveStaticLocationId($cartItem); + if ($locationId === null || $locationId <= 0) { + throw new DisplayException('A deployment location is required before this product can be reserved.'); + } + + usort($configurationOptions, fn (array $left, array $right) => $left['id'] <=> $right['id']); + + $calculatedPrice = round((float) $cartItem->price->total * (int) $cartItem->quantity, 2); + $currencyCode = strtoupper((string) $cartItem->cart->currency_code); + $panel = $this->checkoutPanelIdentity($cartItem); + $pricingIdentity = [ + 'product_id' => (int) $cartItem->product_id, + 'plan_id' => (int) $cartItem->plan_id, + 'currency_code' => $currencyCode, + 'calculated_price' => $calculatedPrice, + 'config_options' => $configurationOptions, + ]; + + return [ + 'customer_id' => $cartItem->cart->user_id !== null + ? (int) $cartItem->cart->user_id + : (auth()->id() !== null ? (int) auth()->id() : null), + 'cart_id' => (int) $cartItem->cart_id, + 'server_extension_id' => $panel['server_extension_id'], + 'panel_identity' => $panel['panel_identity'], + 'product_id' => (int) $cartItem->product_id, + 'plan_id' => (int) $cartItem->plan_id, + 'quantity' => (int) $cartItem->quantity, + 'currency_code' => $currencyCode, + 'location_id' => $locationId, + 'resources' => $resources, + 'calculated_price' => $calculatedPrice, + 'pricing_version' => hash('sha256', $this->canonicalJson($pricingIdentity)), + 'formula_version' => self::FORMULA_VERSION, + 'config_options' => $configurationOptions, + ]; + } + + public function requiresReservation(int $productId): bool + { + $usesPterodactyl = Product::query() + ->whereKey($productId) + ->whereHas('server', fn ($query) => $query->where('extension', 'Pterodactyl')) + ->exists(); + + if (! $usesPterodactyl) { + return false; + } + + return ConfigOption::query() + ->whereHas('products', fn ($query) => $query->whereKey($productId)) + ->where('type', 'dynamic_slider') + ->whereNull('parent_id') + ->get() + ->contains(fn (ConfigOption $option) => in_array( + strtolower((string) $option->getMetadata('resource_type', '')), + ['memory', 'cpu', 'disk'], + true + )); + } + + /** + * @param array $snapshot + * @return array + */ + public function withNode(array $snapshot, int $nodeId): array + { + return $this->canonicalize([ + 'customer_id' => $snapshot['customer_id'], + 'cart_id' => $snapshot['cart_id'], + 'server_extension_id' => $snapshot['server_extension_id'], + 'panel_identity' => $snapshot['panel_identity'], + 'product_id' => $snapshot['product_id'], + 'plan_id' => $snapshot['plan_id'], + 'quantity' => $snapshot['quantity'], + 'currency_code' => $snapshot['currency_code'], + 'location_id' => $snapshot['location_id'], + 'node_id' => $nodeId, + 'resources' => $snapshot['resources'], + 'calculated_price' => $snapshot['calculated_price'], + 'pricing_version' => $snapshot['pricing_version'], + 'formula_version' => $snapshot['formula_version'], + 'config_options' => $snapshot['config_options'], + ]); + } + + /** + * Transfer a guest payload to its authenticated customer without changing + * any pricing, placement, or resource input. + * + * @param array $payload + * @return array + */ + public function withCustomer(array $payload, int $customerId): array + { + $payload['customer_id'] = $customerId; + + return $this->canonicalize($payload); + } + + /** + * @param array $payload + */ + public function fingerprint(array $payload): string + { + return hash('sha256', $this->canonicalJson($payload)); + } + + /** + * Prove that the service still represents the immutable checkout payload. + * + * @param object $reservation + */ + public function assertServiceMatches(Service $service, object $reservation): void + { + $expected = [ + 'server_extension_id' => (int) $reservation->server_extension_id, + 'panel_identity' => (string) $reservation->panel_identity, + 'product_id' => (int) $reservation->product_id, + 'plan_id' => (int) $reservation->plan_id, + 'quantity' => (int) $reservation->quantity, + 'currency_code' => strtoupper((string) $reservation->currency_code), + 'user_id' => (int) $reservation->user_id, + 'memory' => (int) $reservation->memory, + 'cpu' => (int) $reservation->cpu, + 'disk' => (int) $reservation->disk, + 'location' => (int) $reservation->location_id, + ]; + + $properties = collect(ExtensionHelper::getServiceProperties($service)) + ->mapWithKeys(fn ($value, $key) => [strtolower((string) $key) => $value]); + $settings = $service->product->settings() + ->get(['key', 'value']) + ->mapWithKeys(fn ($setting) => [strtolower((string) $setting->key) => $setting->value]); + $server = $service->product->server; + $serverSettings = $server?->settings + ?->pluck('value', 'key') ?? collect(); + + $actual = [ + 'server_extension_id' => (int) $service->product->server_id, + 'panel_identity' => hash( + 'sha256', + $this->normalizePanelUrl((string) $serverSettings->get('host')) + ), + 'product_id' => (int) $service->product_id, + 'plan_id' => (int) $service->plan_id, + 'quantity' => (int) $service->quantity, + 'currency_code' => strtoupper((string) $service->currency_code), + 'user_id' => (int) $service->user_id, + 'memory' => (int) ($properties->get('memory') ?? $settings->get('memory')), + 'cpu' => (int) ($properties->get('cpu') ?? $settings->get('cpu')), + 'disk' => (int) ($properties->get('disk') ?? $settings->get('disk')), + 'location' => $this->serviceLocationId($service, $properties->get('location')), + ]; + + if ($expected !== $actual) { + throw new \RuntimeException('The service configuration does not match its capacity reservation.'); + } + } + + /** + * @return array{server_extension_id: int, panel_identity: string} + */ + private function checkoutPanelIdentity(CartItem $cartItem): array + { + $server = $cartItem->product->server; + $serverSettings = $server?->settings?->pluck('value', 'key') ?? collect(); + $capacityExtension = Extension::query() + ->where('extension', 'DynamicPterodactyl') + ->where('enabled', true) + ->first(); + $capacitySettings = $capacityExtension?->settings() + ->pluck('value', 'key') ?? collect(); + + $provisioningUrl = $this->normalizePanelUrl((string) $serverSettings->get('host')); + $capacityUrl = $this->normalizePanelUrl((string) $capacitySettings->get('pterodactyl_url')); + + if ( + $server === null + || $server->extension !== 'Pterodactyl' + || $provisioningUrl === '' + || $capacityUrl === '' + || ! hash_equals($provisioningUrl, $capacityUrl) + ) { + throw new DisplayException( + 'The capacity service and this product must use the same Pterodactyl panel.' + ); + } + + return [ + 'server_extension_id' => (int) $server->id, + 'panel_identity' => hash('sha256', $provisioningUrl), + ]; + } + + private function normalizePanelUrl(string $url): string + { + return strtolower(rtrim(trim($url), '/')); + } + + private function resolveLocationId(ConfigOption $option, mixed $value): ?int + { + if ($value === null || $value === '') { + return null; + } + + if ($option->type === 'dynamic_slider') { + return is_numeric($value) ? (int) $value : null; + } + + $selectedChild = $option->children->firstWhere('id', (int) $value); + $resolved = $selectedChild?->env_variable ?? $value; + + return is_numeric($resolved) ? (int) $resolved : null; + } + + private function resolveStaticLocationId(CartItem $cartItem): ?int + { + $settings = $cartItem->product->settings()->pluck('value', 'key'); + $locations = $settings->get('location_ids'); + + if (is_string($locations)) { + $decoded = json_decode($locations, true); + $locations = json_last_error() === JSON_ERROR_NONE ? $decoded : $locations; + } + + $locations = is_array($locations) ? array_values($locations) : [$locations]; + $locations = array_values(array_filter($locations, fn ($location) => is_numeric($location))); + + return count($locations) === 1 ? (int) $locations[0] : null; + } + + /** + * Static Pterodactyl limits fill resources whose sliders are intentionally + * disabled. They become part of the same immutable payload. + * + * @return array{memory?: int, cpu?: int, disk?: int} + */ + private function resolveStaticResources(CartItem $cartItem): array + { + $settings = $cartItem->product->settings() + ->get(['key', 'value']) + ->mapWithKeys(fn ($setting) => [strtolower((string) $setting->key) => $setting->value]); + $resources = []; + + foreach (['memory', 'cpu', 'disk'] as $resourceType) { + $value = $settings->get($resourceType); + $minimum = $resourceType === 'cpu' ? 0 : 1; + + if (is_numeric($value) && (float) $value >= $minimum) { + $resources[$resourceType] = (int) $value; + } + } + + return $resources; + } + + private function serviceLocationId(Service $service, mixed $propertyLocation): int + { + if (is_numeric($propertyLocation)) { + return (int) $propertyLocation; + } + + $locations = $service->product->settings()->where('key', 'location_ids')->value('value'); + if (is_string($locations)) { + $decoded = json_decode($locations, true); + $locations = json_last_error() === JSON_ERROR_NONE ? $decoded : $locations; + } + + $locations = is_array($locations) ? array_values($locations) : [$locations]; + $locations = array_values(array_filter($locations, fn ($location) => is_numeric($location))); + + return count($locations) === 1 ? (int) $locations[0] : 0; + } + + /** + * @return array + */ + private function canonicalize(array $value): array + { + foreach ($value as $key => $item) { + if (is_array($item)) { + $value[$key] = $this->canonicalize($item); + } + } + + if (! array_is_list($value)) { + ksort($value); + } + + return $value; + } + + private function canonicalJson(array $value): string + { + return json_encode( + $this->canonicalize($value), + JSON_THROW_ON_ERROR | JSON_PRESERVE_ZERO_FRACTION | JSON_UNESCAPED_SLASHES + ); + } +} diff --git a/Services/ReservationService.php b/Services/ReservationService.php index 451aa24..d656553 100644 --- a/Services/ReservationService.php +++ b/Services/ReservationService.php @@ -2,13 +2,15 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Services; +use App\Exceptions\DisplayException; +use App\Models\CartItem; use App\Models\Extension; +use App\Models\Service; use App\Models\User; use Carbon\Carbon; -use Illuminate\Database\QueryException; +use Carbon\CarbonInterface; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Gate; -use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\ResourceReservation; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\Concerns\AuditsExtensionActions; @@ -17,16 +19,23 @@ class ReservationService { use AuditsExtensionActions; + private const PROVISIONING_LEASE_MINUTES = 5; + private NodeSelectionService $nodeService; + private ReservationConfigurationService $configurationService; + private int $ttlMinutes; public function __construct( - NodeSelectionService $nodeService + NodeSelectionService $nodeService, + ReservationConfigurationService $configurationService ) { $this->nodeService = $nodeService; + $this->configurationService = $configurationService; $config = Extension::where('extension', 'DynamicPterodactyl') + ->where('enabled', true) ->first() ?->settings ->pluck('value', 'key') @@ -35,254 +44,481 @@ public function __construct( } /** - * Create a resource reservation + * Create or refresh the one server-owned hold for a cart item. + * + * Browser-provided tokens and idempotency keys are deliberately not accepted. * - * Uses database transaction with pessimistic locking - * Retries up to 5 times on deadlock + * @return array{id: int, node_id: int, expires_at: string, status: string} */ - public function create( - int $productId, - int $locationId, - array $resources, - ?int $cartItemId = null, - ?int $userId = null, - ?string $idempotencyKey = null - ): array { - try { - return DB::transaction(function () use ($productId, $locationId, $resources, $cartItemId, $userId, $idempotencyKey) { - // Lock pending reservations for this location + public function reserveForCartItem(CartItem $cartItem): array + { + $snapshot = $this->configurationService->forCartItem($cartItem); + $ownerId = $snapshot['customer_id']; + + return DB::transaction(function () use ($cartItem, $snapshot, $ownerId) { + DB::table('ptero_resource_reservations') + ->where('location_id', $snapshot['location_id']) + ->where('status', 'pending') + ->lockForUpdate() + ->get(); + + $existing = DB::table('ptero_resource_reservations') + ->where('cart_item_id', $cartItem->id) + ->where('status', 'pending') + ->lockForUpdate() + ->first(); + + if ($existing !== null && $existing->user_id !== null && (int) $existing->user_id !== (int) $ownerId) { + throw new DisplayException('This cart capacity hold belongs to a different customer.'); + } + + if ($existing !== null && Carbon::parse($existing->expires_at)->isPast()) { DB::table('ptero_resource_reservations') - ->where('location_id', $locationId) - ->where('status', 'pending') - ->lockForUpdate() - ->get(); - - if ($idempotencyKey !== null) { - $this->expireStaleIdempotencyReservations($userId, $idempotencyKey); - - $existingReservation = $this->getActiveByIdempotencyKey($userId, $idempotencyKey); - if ($existingReservation) { - Log::info('Returning existing reservation for idempotent create request', [ - 'reservation_id' => $existingReservation->id, - 'user_id' => $userId, - 'idempotency_key' => $idempotencyKey, - ]); - - return $this->presentReservation($existingReservation); - } - } + ->where('id', $existing->id) + ->update([ + 'status' => 'expired', + 'updated_at' => now(), + ]); + $existing = null; + } + + if ($existing !== null && $this->matchesSnapshot($existing, $snapshot)) { + $expiresAt = now()->addMinutes($this->ttlMinutes); + + DB::table('ptero_resource_reservations') + ->where('id', $existing->id) + ->update([ + 'user_id' => $ownerId, + 'expires_at' => $expiresAt, + 'updated_at' => now(), + ]); + + return [ + 'id' => (int) $existing->id, + 'node_id' => (int) $existing->node_id, + 'expires_at' => $expiresAt->toIso8601String(), + 'status' => 'pending', + ]; + } + + $excludedToken = $existing?->token; + if ($existing !== null) { + DB::table('ptero_resource_reservations') + ->where('id', $existing->id) + ->update([ + 'status' => 'cancelled', + 'admin_notes' => 'Replaced after cart configuration changed.', + 'updated_at' => now(), + ]); + } - $node = $this->nodeService->selectBestNode($locationId, $resources); + $node = $this->nodeService->selectBestNode( + $snapshot['location_id'], + $snapshot['resources'], + $excludedToken + ); - if (!$node) { - throw new \RuntimeException('No node with sufficient resources available'); + if ($node === null) { + throw new DisplayException('No node has enough capacity for this configuration.'); + } + + $payload = $this->configurationService->withNode($snapshot, (int) $node['node_id']); + $fingerprint = $this->configurationService->fingerprint($payload); + $token = Str::random(64); + $expiresAt = now()->addMinutes($this->ttlMinutes); + + $id = DB::table('ptero_resource_reservations')->insertGetId([ + 'token' => $token, + 'idempotency_key' => null, + 'cart_item_id' => $cartItem->id, + 'cart_id' => $snapshot['cart_id'], + 'server_extension_id' => $snapshot['server_extension_id'], + 'panel_identity' => $snapshot['panel_identity'], + 'service_id' => null, + 'user_id' => $ownerId, + 'product_id' => $snapshot['product_id'], + 'plan_id' => $snapshot['plan_id'], + 'quantity' => $snapshot['quantity'], + 'currency_code' => $snapshot['currency_code'], + 'configuration_fingerprint' => $fingerprint, + 'configuration_payload' => json_encode($payload, JSON_THROW_ON_ERROR), + 'pricing_version' => $snapshot['pricing_version'], + 'formula_version' => $snapshot['formula_version'], + 'node_id' => $node['node_id'], + 'location_id' => $snapshot['location_id'], + 'memory' => $snapshot['resources']['memory'], + 'cpu' => $snapshot['resources']['cpu'], + 'disk' => $snapshot['resources']['disk'], + 'calculated_price' => $snapshot['calculated_price'], + 'pricing_breakdown' => json_encode([], JSON_THROW_ON_ERROR), + 'status' => 'pending', + 'expires_at' => $expiresAt, + 'created_at' => now(), + 'updated_at' => now(), + ]); + + $this->safeAudit('created', 'reservation', $id, [ + 'reservation_id' => $id, + 'configuration_fingerprint' => $fingerprint, + 'product_id' => $snapshot['product_id'], + 'plan_id' => $snapshot['plan_id'], + 'location_id' => $snapshot['location_id'], + 'node_id' => $node['node_id'], + 'memory' => $snapshot['resources']['memory'], + 'cpu' => $snapshot['resources']['cpu'], + 'disk' => $snapshot['resources']['disk'], + 'cart_item_id' => $cartItem->id, + ]); + + return [ + 'id' => $id, + 'node_id' => (int) $node['node_id'], + 'expires_at' => $expiresAt->toIso8601String(), + 'status' => 'pending', + ]; + }, 5); + } + + /** + * Transfer every guest hold with the cart inside the login transaction. + */ + public function transferCartOwnership(int $cartId, int $userId): int + { + return DB::transaction(function () use ($cartId, $userId) { + $reservations = DB::table('ptero_resource_reservations') + ->where('cart_id', $cartId) + ->where('status', 'pending') + ->lockForUpdate() + ->get(); + + foreach ($reservations as $reservation) { + if ($reservation->user_id !== null && (int) $reservation->user_id !== $userId) { + throw new \RuntimeException('A capacity hold in this cart belongs to a different customer.'); } - $token = Str::random(64); - $expiresAt = now()->addMinutes($this->ttlMinutes); + if ($reservation->user_id !== null) { + continue; + } - $id = DB::table('ptero_resource_reservations')->insertGetId([ - 'token' => $token, - 'idempotency_key' => $idempotencyKey, - 'cart_item_id' => $cartItemId, - 'user_id' => $userId, - 'node_id' => $node['node_id'], - 'location_id' => $locationId, - 'memory' => $resources['memory'], - 'cpu' => $resources['cpu'], - 'disk' => $resources['disk'], - 'calculated_price' => 0, - 'pricing_breakdown' => json_encode([]), - 'status' => 'pending', - 'expires_at' => $expiresAt, - 'created_at' => now(), - 'updated_at' => now(), - ]); + $payload = json_decode( + (string) $reservation->configuration_payload, + true, + 512, + JSON_THROW_ON_ERROR + ); + if (! is_array($payload) || (int) ($payload['cart_id'] ?? 0) !== $cartId) { + throw new \RuntimeException('Capacity hold payload does not match its cart.'); + } - $this->safeAudit('created', 'reservation', $id, [ - 'token_prefix' => substr($token, 0, 8) . '...', - 'product_id' => $productId, - 'location_id' => $locationId, - 'node_id' => $node['node_id'], - 'memory' => $resources['memory'], - 'cpu' => $resources['cpu'], - 'disk' => $resources['disk'], - 'price' => 0, - 'cart_item_id' => $cartItemId, - ]); + $payload = $this->configurationService->withCustomer($payload, $userId); - return $this->presentReservation((object) [ - 'id' => $id, - 'token' => $token, - 'node_id' => $node['node_id'], - 'node_name' => $node['name'] ?? null, - 'expires_at' => $expiresAt, - 'calculated_price' => 0, - 'pricing_breakdown' => [], - 'status' => 'pending', - ]); - }, 5); // 5 retry attempts for deadlock - } catch (QueryException $exception) { - if ($this->isActiveIdempotencyDuplicate($exception, $userId, $idempotencyKey)) { - $existingReservation = $this->getActiveByIdempotencyKey($userId, $idempotencyKey); - if ($existingReservation) { - Log::info('Returning existing reservation after duplicate idempotency insert race', [ - 'reservation_id' => $existingReservation->id, + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ 'user_id' => $userId, - 'idempotency_key' => $idempotencyKey, + 'configuration_payload' => json_encode($payload, JSON_THROW_ON_ERROR), + 'configuration_fingerprint' => $this->configurationService->fingerprint($payload), + 'updated_at' => now(), ]); - - return $this->presentReservation($existingReservation); - } } - throw $exception; - } + return $reservations->whereNull('user_id')->count(); + }, 5); } - private function getActiveByIdempotencyKey(?int $userId, string $idempotencyKey): ?object - { - return DB::table('ptero_resource_reservations') - ->when($userId === null, fn ($query) => $query->whereNull('user_id'), fn ($query) => $query->where('user_id', $userId)) - ->where('idempotency_key', $idempotencyKey) - ->where(function ($query) { - $query->where('status', 'confirmed') - ->orWhere(function ($subQuery) { - $subQuery->where('status', 'pending') - ->where('expires_at', '>', now()); - }); - }) - ->orderByDesc('id') - ->first(); + /** + * Attach the validated cart hold to the newly created service. + */ + public function bindCartItemToService( + CartItem $cartItem, + Service $service, + User $user, + CarbonInterface $holdUntil + ): void { + $snapshot = $this->configurationService->forCartItem($cartItem); + + DB::transaction(function () use ($cartItem, $service, $user, $holdUntil, $snapshot) { + $reservation = DB::table('ptero_resource_reservations') + ->where('cart_item_id', $cartItem->id) + ->where('status', 'pending') + ->lockForUpdate() + ->first(); + + if ($reservation === null || Carbon::parse($reservation->expires_at)->isPast()) { + throw new DisplayException('Capacity hold expired during checkout. Please reconfigure this product.'); + } + + if ($reservation->user_id !== null && (int) $reservation->user_id !== (int) $user->id) { + throw new DisplayException('This capacity hold belongs to a different customer.'); + } + + if ($reservation->service_id !== null && (int) $reservation->service_id !== (int) $service->id) { + throw new \RuntimeException('This capacity hold is already bound to another service.'); + } + + if (! $this->matchesSnapshot($reservation, $snapshot)) { + throw new DisplayException('The cart configuration changed after capacity was reserved. Please reconfigure this product.'); + } + + if ( + (int) $service->product_id !== (int) $reservation->product_id + || (int) $service->plan_id !== (int) $reservation->plan_id + || (int) $service->quantity !== (int) $reservation->quantity + || strtoupper((string) $service->currency_code) !== strtoupper((string) $reservation->currency_code) + ) { + throw new \RuntimeException('The new service does not match its capacity reservation.'); + } + + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ + 'service_id' => $service->id, + 'user_id' => $user->id, + 'expires_at' => $holdUntil, + 'updated_at' => now(), + ]); + + $this->safeAudit('reservation_bound', 'resource_reservation', $reservation->id, [ + 'service_id' => $service->id, + 'user_id' => $user->id, + 'configuration_fingerprint' => $reservation->configuration_fingerprint, + ]); + }, 5); } /** - * Confirm a reservation (after successful payment) + * Lock and validate a hold immediately before the external create request. * - * @param User|null $actor Authenticated user performing the action, or null for system context. - * When provided, authorization is enforced via ResourceReservationPolicy. - * Controller callers MUST pass the actor; system callers MAY pass null. + * @return array{ + * reservation_id: int, + * panel_identity: string, + * node_id: int, + * location_id: int, + * memory: int, + * cpu: int, + * disk: int, + * provisioning_lease_id: string|null, + * already_consumed: bool + * }|null */ - public function confirm(string $token, int $serviceId, ?User $actor = null): bool + public function beginProvisioning(Service $service): ?array { - $reservation = $this->getByToken($token); + return DB::transaction(function () use ($service) { + $reservation = DB::table('ptero_resource_reservations') + ->where('service_id', $service->id) + ->lockForUpdate() + ->first(); + + if ($reservation === null) { + if ($this->configurationService->requiresReservation($service->product_id)) { + throw new \RuntimeException('Dynamic resource service has no capacity reservation.'); + } - if ($actor !== null) { - $reservationModel = ResourceReservation::query()->where('token', $token)->first(); + return null; + } - if ($reservationModel !== null) { - Gate::forUser($actor)->authorize('confirm', $reservationModel); + if ($reservation->status === 'confirmed') { + return $this->provisioningContext($reservation, true); + } + + if ($reservation->status !== 'pending') { + throw new \RuntimeException("Capacity reservation is {$reservation->status}."); } - } - $reservationId = $reservation?->id ?? 0; + if (Carbon::parse($reservation->expires_at)->isPast()) { + throw new \RuntimeException('Capacity reservation expired before provisioning.'); + } - $rows = DB::table('ptero_resource_reservations') - ->where('token', $token) + if ( + $reservation->provisioning_started_at !== null + && Carbon::parse($reservation->provisioning_started_at) + ->greaterThan(now()->subMinutes(self::PROVISIONING_LEASE_MINUTES)) + ) { + throw new \RuntimeException('Capacity reservation is already being provisioned.'); + } + + $this->configurationService->assertServiceMatches($service, $reservation); + + $leaseExpiresAt = now()->addMinutes(self::PROVISIONING_LEASE_MINUTES); + $currentExpiresAt = Carbon::parse($reservation->expires_at); + $leaseId = Str::random(64); + + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ + 'provisioning_started_at' => now(), + 'provisioning_lease_id' => $leaseId, + 'expires_at' => $currentExpiresAt->greaterThan($leaseExpiresAt) + ? $currentExpiresAt + : $leaseExpiresAt, + 'last_provisioning_error' => null, + 'updated_at' => now(), + ]); + + return $this->provisioningContext($reservation, false, $leaseId); + }, 5); + } + + public function completeProvisioning(int $serviceId, ?string $leaseId = null): bool + { + return DB::transaction(function () use ($serviceId, $leaseId) { + $reservation = DB::table('ptero_resource_reservations') + ->where('service_id', $serviceId) + ->lockForUpdate() + ->first(); + + if ($reservation === null) { + return false; + } + + if ($reservation->status === 'confirmed') { + return true; + } + + if ($reservation->status !== 'pending') { + throw new \RuntimeException("Cannot consume a {$reservation->status} capacity reservation."); + } + + if ( + $leaseId === null + || $reservation->provisioning_lease_id === null + || ! hash_equals((string) $reservation->provisioning_lease_id, $leaseId) + ) { + throw new \RuntimeException('Provisioning lease no longer owns this capacity reservation.'); + } + + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ + 'status' => 'confirmed', + 'consumed_at' => now(), + 'provisioning_started_at' => null, + 'provisioning_lease_id' => null, + 'last_provisioning_error' => null, + 'updated_at' => now(), + ]); + + $this->safeAudit('reservation_consumed', 'resource_reservation', $reservation->id, [ + 'service_id' => $serviceId, + 'node_id' => $reservation->node_id, + 'configuration_fingerprint' => $reservation->configuration_fingerprint, + ]); + + return true; + }, 5); + } + + public function failProvisioning( + int $serviceId, + ?string $leaseId, + \Throwable $exception + ): void + { + DB::table('ptero_resource_reservations') + ->where('service_id', $serviceId) ->where('status', 'pending') - ->where('expires_at', '>', now()) + ->where('provisioning_lease_id', $leaseId) ->update([ - 'status' => 'confirmed', - 'service_id' => $serviceId, + 'provisioning_started_at' => null, + 'provisioning_lease_id' => null, + 'last_provisioning_error' => Str::limit($exception->getMessage(), 1000, ''), 'updated_at' => now(), ]); + } - if ($rows > 0) { - $this->safeAudit('reservation_confirmed', 'resource_reservation', $reservationId, [ - 'token_prefix' => substr($token, 0, 8), - 'service_id' => $serviceId, - 'node_id' => $reservation->node_id ?? null, - ]); - } + public function cancelForCartItem(int $cartItemId): bool + { + return DB::transaction(function () use ($cartItemId) { + $reservation = DB::table('ptero_resource_reservations') + ->where('cart_item_id', $cartItemId) + ->where('status', 'pending') + ->lockForUpdate() + ->first(); + + if ($reservation === null || $reservation->service_id !== null) { + return false; + } - return $rows > 0; + return DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ + 'status' => 'cancelled', + 'admin_notes' => 'Cart item removed.', + 'updated_at' => now(), + ]) > 0; + }, 5); } /** - * Cancel a reservation - * - * @param User|null $actor Authenticated user performing the action, or null for system context. - * When provided, authorization is enforced via ResourceReservationPolicy. - * Controller callers MUST pass the actor; system callers MAY pass null. + * Admin/system cancellation by the opaque internal token. */ - public function cancel(string $token, ?string $reason = null, string $source = 'system', ?User $actor = null): bool - { + public function cancel( + string $token, + ?string $reason = null, + string $source = 'system', + ?User $actor = null + ): bool { $reservation = $this->getByToken($token); - - if (!$reservation) { + if ($reservation === null) { return false; } if ($actor !== null) { $reservationModel = ResourceReservation::query()->where('token', $token)->first(); - if ($reservationModel !== null) { Gate::forUser($actor)->authorize('cancel', $reservationModel); } } - $result = DB::table('ptero_resource_reservations') + $updated = DB::table('ptero_resource_reservations') ->where('token', $token) ->where('status', 'pending') + ->whereNull('service_id') ->update([ 'status' => 'cancelled', 'admin_notes' => $reason, 'updated_at' => now(), ]) > 0; - if ($result) { + if ($updated) { $this->safeAudit('reservation_cancelled', 'resource_reservation', $reservation->id, [ - 'token_prefix' => substr($token, 0, 8), - 'node_id' => $reservation->node_id ?? null, + 'source' => $source, + 'node_id' => $reservation->node_id, ]); } - return $result; + return $updated; } /** - * Extend reservation TTL - * - * @param User|null $actor Authenticated user performing the action, or null for system context. - * When provided, authorization is enforced via ResourceReservationPolicy. - * Controller callers MUST pass the actor; system callers MAY pass null. + * Admin-only TTL extension. */ public function extend(string $token, int $additionalMinutes = 15, ?User $actor = null): bool { - $reservation = $this->getByToken($token); + $reservation = ResourceReservation::query()->where('token', $token)->first(); + if ($reservation === null) { + return false; + } if ($actor !== null) { - $reservationModel = ResourceReservation::query()->where('token', $token)->first(); - - if ($reservationModel !== null) { - Gate::forUser($actor)->authorize('extend', $reservationModel); - } + Gate::forUser($actor)->authorize('extend', $reservation); } - $reservationId = $reservation?->id ?? 0; + if ($reservation->status !== 'pending') { + return false; + } - $rows = DB::table('ptero_resource_reservations') - ->where('token', $token) - ->where('status', 'pending') - ->update([ - 'expires_at' => DB::raw("DATE_ADD(expires_at, INTERVAL {$additionalMinutes} MINUTE)"), - 'updated_at' => now(), - ]); + $reservation->expires_at = $reservation->expires_at->addMinutes($additionalMinutes); + $reservation->save(); - if ($rows > 0) { - $this->safeAudit('reservation_extended', 'resource_reservation', $reservationId, [ - 'token_prefix' => substr($token, 0, 8), - 'additional_minutes' => $additionalMinutes, - 'node_id' => $reservation->node_id ?? null, - ]); - } + $this->safeAudit('reservation_extended', 'resource_reservation', $reservation->id, [ + 'additional_minutes' => $additionalMinutes, + 'node_id' => $reservation->node_id, + ]); - return $rows > 0; + return true; } - /** - * Get reservation by token - */ public function getByToken(string $token): ?object { return DB::table('ptero_resource_reservations') @@ -290,9 +526,6 @@ public function getByToken(string $token): ?object ->first(); } - /** - * Get reservation by cart item - */ public function getByCartItem(int $cartItemId): ?object { return DB::table('ptero_resource_reservations') @@ -302,10 +535,6 @@ public function getByCartItem(int $cartItemId): ?object } /** - * Get all reservations as a paginatable Eloquent builder (for admin API). - * - * Does NOT modify getAll() — callers of that method are unaffected. - * * @param array $filters * @return \Illuminate\Database\Eloquent\Builder */ @@ -313,25 +542,22 @@ public function queryAll(array $filters = []): \Illuminate\Database\Eloquent\Bui { $query = ResourceReservation::query(); - if (!empty($filters['status'])) { + if (! empty($filters['status'])) { $query->where('status', $filters['status']); } - if (!empty($filters['location_id'])) { + if (! empty($filters['location_id'])) { $query->where('location_id', (int) $filters['location_id']); } - if (!empty($filters['node_id'])) { + if (! empty($filters['node_id'])) { $query->where('node_id', (int) $filters['node_id']); } - if (!empty($filters['user_id'])) { + if (! empty($filters['user_id'])) { $query->where('user_id', (int) $filters['user_id']); } - return $query->orderBy('created_at', 'desc')->orderBy('id', 'desc'); + return $query->orderByDesc('created_at')->orderByDesc('id'); } - /** - * Get reservation statistics - */ public function getStatistics(string $period = '30d'): array { $startDate = match ($period) { @@ -354,7 +580,7 @@ public function getStatistics(string $period = '30d'): array ->where('status', 'confirmed') ->sum('calculated_price'); - $avgResources = DB::table('ptero_resource_reservations') + $average = DB::table('ptero_resource_reservations') ->where('created_at', '>=', $startDate) ->where('status', 'confirmed') ->selectRaw('AVG(memory) as avg_memory, AVG(cpu) as avg_cpu, AVG(disk) as avg_disk') @@ -374,16 +600,13 @@ public function getStatistics(string $period = '30d'): array ? round($confirmed / ($confirmed + $expired + $cancelled) * 100, 1) : 0, 'average_resources' => [ - 'memory' => round($avgResources->avg_memory ?? 0), - 'cpu' => round($avgResources->avg_cpu ?? 0), - 'disk' => round($avgResources->avg_disk ?? 0), + 'memory' => round($average->avg_memory ?? 0), + 'cpu' => round($average->avg_cpu ?? 0), + 'disk' => round($average->avg_disk ?? 0), ], ]; } - /** - * Cleanup expired reservations (called by scheduled job) - */ public function cleanupExpired(): int { $count = DB::table('ptero_resource_reservations') @@ -391,6 +614,8 @@ public function cleanupExpired(): int ->where('expires_at', '<', now()) ->update([ 'status' => 'expired', + 'provisioning_started_at' => null, + 'provisioning_lease_id' => null, 'updated_at' => now(), ]); @@ -404,50 +629,50 @@ public function cleanupExpired(): int return $count; } - private function presentReservation(object $reservation): array + /** + * @param object $reservation + * @param array $snapshot + */ + private function matchesSnapshot(object $reservation, array $snapshot): bool { - $expiresAt = $reservation->expires_at ? Carbon::parse($reservation->expires_at) : null; + $payload = $this->configurationService->withNode($snapshot, (int) $reservation->node_id); - return [ - 'id' => $reservation->id, - 'token' => $reservation->token, - 'node_id' => $reservation->node_id, - 'node_name' => $reservation->node_name ?? null, - 'expires_at' => $expiresAt?->toIso8601String(), - 'ttl_minutes' => $expiresAt && $reservation->status === 'pending' - ? max(0, now()->diffInMinutes($expiresAt, false)) - : 0, - 'pricing' => [ - 'total' => (float) $reservation->calculated_price, - 'breakdown' => is_array($reservation->pricing_breakdown) - ? $reservation->pricing_breakdown - : json_decode($reservation->pricing_breakdown ?? '[]', true) ?? [], - 'model' => 'stored', - ], - 'status' => $reservation->status, - ]; - } - - private function expireStaleIdempotencyReservations(?int $userId, string $idempotencyKey): void - { - DB::table('ptero_resource_reservations') - ->when($userId === null, fn ($query) => $query->whereNull('user_id'), fn ($query) => $query->where('user_id', $userId)) - ->where('idempotency_key', $idempotencyKey) - ->where('status', 'pending') - ->where('expires_at', '<=', now()) - ->update([ - 'status' => 'expired', - 'updated_at' => now(), - ]); + return hash_equals( + (string) $reservation->configuration_fingerprint, + $this->configurationService->fingerprint($payload) + ); } - private function isActiveIdempotencyDuplicate(QueryException $exception, ?int $userId, ?string $idempotencyKey): bool + /** + * @param object $reservation + * @return array{ + * reservation_id: int, + * panel_identity: string, + * node_id: int, + * location_id: int, + * memory: int, + * cpu: int, + * disk: int, + * provisioning_lease_id: string|null, + * already_consumed: bool + * } + */ + private function provisioningContext( + object $reservation, + bool $alreadyConsumed, + ?string $leaseId = null + ): array { - if ($userId === null || $idempotencyKey === null) { - return false; - } - - return str_contains($exception->getMessage(), 'ptero_reservations_active_idempotency_unique') - || ($exception->getCode() === '23000' && str_contains($exception->getMessage(), 'Duplicate entry')); + return [ + 'reservation_id' => (int) $reservation->id, + 'panel_identity' => (string) $reservation->panel_identity, + 'node_id' => (int) $reservation->node_id, + 'location_id' => (int) $reservation->location_id, + 'memory' => (int) $reservation->memory, + 'cpu' => (int) $reservation->cpu, + 'disk' => (int) $reservation->disk, + 'provisioning_lease_id' => $leaseId, + 'already_consumed' => $alreadyConsumed, + ]; } } diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index f344fe2..ce6c485 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -30,9 +30,10 @@ public function getLocationAvailability(int $locationId, ?string $excludeReserva $locationData = [ 'location_id' => $locationId, 'nodes' => [], - 'max_available' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], - 'total_capacity' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], + 'max_available' => ['memory' => 0, 'cpu' => null, 'disk' => 0], + 'total_capacity' => ['memory' => 0, 'cpu' => null, 'disk' => 0], 'total_allocated' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], + 'cpu_capacity_enforced' => false, ]; foreach ($nodes as $node) { @@ -44,10 +45,6 @@ public function getLocationAvailability(int $locationId, ?string $excludeReserva $locationData['max_available']['memory'], $nodeAvailability['available']['memory'] ); - $locationData['max_available']['cpu'] = max( - $locationData['max_available']['cpu'], - $nodeAvailability['available']['cpu'] - ); $locationData['max_available']['disk'] = max( $locationData['max_available']['disk'], $nodeAvailability['available']['disk'] @@ -55,7 +52,6 @@ public function getLocationAvailability(int $locationId, ?string $excludeReserva // Aggregate totals $locationData['total_capacity']['memory'] += $nodeAvailability['total']['memory']; - $locationData['total_capacity']['cpu'] += $nodeAvailability['total']['cpu']; $locationData['total_capacity']['disk'] += $nodeAvailability['total']['disk']; $locationData['total_allocated']['memory'] += $nodeAvailability['allocated']['memory']; @@ -88,9 +84,9 @@ public function buildClusterSnapshot(): array $knownLocationIds[$location['id']] = true; $snapshot['by_location'][$location['id']] = [ 'nodes' => [], - 'totals' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], + 'totals' => ['memory' => 0, 'cpu' => null, 'disk' => 0], 'allocated' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], - 'available' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], + 'available' => ['memory' => 0, 'cpu' => null, 'disk' => 0], ]; } @@ -123,13 +119,11 @@ public function buildClusterSnapshot(): array $snapshot['by_location'][$locationId]['nodes'][] = $nodeId; $snapshot['by_location'][$locationId]['totals']['memory'] += $availability['total']['memory']; - $snapshot['by_location'][$locationId]['totals']['cpu'] += $availability['total']['cpu']; $snapshot['by_location'][$locationId]['totals']['disk'] += $availability['total']['disk']; $snapshot['by_location'][$locationId]['allocated']['memory'] += $availability['allocated']['memory']; $snapshot['by_location'][$locationId]['allocated']['cpu'] += $availability['allocated']['cpu']; $snapshot['by_location'][$locationId]['allocated']['disk'] += $availability['allocated']['disk']; $snapshot['by_location'][$locationId]['available']['memory'] += $availability['available']['memory']; - $snapshot['by_location'][$locationId]['available']['cpu'] += $availability['available']['cpu']; $snapshot['by_location'][$locationId]['available']['disk'] += $availability['available']['disk']; } @@ -192,7 +186,11 @@ public function testConnection(): array } /** - * Verify resources are still available (called at payment time) + * Verify authoritative memory and disk capacity. + * + * CPU is intentionally not checked because Pterodactyl does not publish node + * CPU inventory. The requested CPU limit is still reserved as identity data + * and passed to server creation. */ public function verifyAvailability(int $nodeId, array $requirements, ?string $excludeReservationToken = null): bool { @@ -206,7 +204,6 @@ public function verifyAvailability(int $nodeId, array $requirements, ?string $ex $availability = $this->calculateNodeAvailability($nodeWithServers, $excludeReservationToken); return $availability['available']['memory'] >= $requirements['memory'] - && $availability['available']['cpu'] >= $requirements['cpu'] && $availability['available']['disk'] >= $requirements['disk']; } @@ -277,11 +274,9 @@ private function buildNodeAvailabilityFromServers(array $node, array $servers, a $effectiveMemory = $node['memory'] * (1 + ($node['memory_overallocate'] ?? 0) / 100); $effectiveDisk = $node['disk'] * (1 + ($node['disk_overallocate'] ?? 0) / 100); - $effectiveCpu = $node['cpu_threads'] * 100; - $available = [ 'memory' => max(0, (int) $effectiveMemory - $allocated['memory'] - $pendingReservations['memory']), - 'cpu' => max(0, (int) $effectiveCpu - $allocated['cpu'] - $pendingReservations['cpu']), + 'cpu' => null, 'disk' => max(0, (int) $effectiveDisk - $allocated['disk'] - $pendingReservations['disk']), ]; @@ -292,13 +287,14 @@ private function buildNodeAvailabilityFromServers(array $node, array $servers, a 'maintenance_mode' => $node['maintenance_mode'] ?? false, 'total' => [ 'memory' => (int) $effectiveMemory, - 'cpu' => (int) $effectiveCpu, + 'cpu' => null, 'disk' => (int) $effectiveDisk, ], 'allocated' => $allocated, 'reserved' => $pendingReservations, 'available' => $available, 'server_count' => count($servers), + 'cpu_capacity_enforced' => false, 'utilization' => [ 'memory' => $effectiveMemory > 0 ? round(($allocated['memory'] + $pendingReservations['memory']) / $effectiveMemory * 100, 1) @@ -776,6 +772,7 @@ private function getNodeLocation(int $nodeId): int private function getExtensionConfig(): array { return Extension::where('extension', 'DynamicPterodactyl') + ->where('enabled', true) ->first() ?->settings ->pluck('value', 'key') diff --git a/database/migrations/2026_07_25_000001_add_checkout_identity_to_ptero_resource_reservations.php b/database/migrations/2026_07_25_000001_add_checkout_identity_to_ptero_resource_reservations.php new file mode 100644 index 0000000..ec1fd00 --- /dev/null +++ b/database/migrations/2026_07_25_000001_add_checkout_identity_to_ptero_resource_reservations.php @@ -0,0 +1,87 @@ +unsignedBigInteger('cart_id')->nullable()->after('cart_item_id'); + $table->unsignedBigInteger('server_extension_id')->nullable()->after('cart_id'); + $table->string('panel_identity', 64)->nullable()->after('server_extension_id'); + $table->unsignedBigInteger('product_id')->nullable()->after('user_id'); + $table->unsignedBigInteger('plan_id')->nullable()->after('product_id'); + $table->unsignedInteger('quantity')->default(1)->after('plan_id'); + $table->string('currency_code', 3)->nullable()->after('quantity'); + $table->string('configuration_fingerprint', 64)->nullable()->after('currency_code'); + $table->json('configuration_payload')->nullable()->after('configuration_fingerprint'); + $table->string('pricing_version', 64)->nullable()->after('configuration_payload'); + $table->string('formula_version', 64)->nullable()->after('pricing_version'); + $table->timestamp('provisioning_started_at')->nullable()->after('expires_at'); + $table->string('provisioning_lease_id', 64)->nullable()->after('provisioning_started_at'); + $table->timestamp('consumed_at')->nullable()->after('provisioning_lease_id'); + $table->text('last_provisioning_error')->nullable()->after('consumed_at'); + + $table->unsignedBigInteger('active_cart_item_id') + ->nullable() + ->storedAs("CASE WHEN status = 'pending' THEN cart_item_id ELSE NULL END") + ->after('cart_item_id'); + }); + + // Every pre-migration pending row came from one of the two superseded + // token flows and lacks the immutable identity needed for safe use. + // Active carts will acquire a fresh hold on edit or checkout. + DB::table('ptero_resource_reservations') + ->where('status', 'pending') + ->whereNull('configuration_fingerprint') + ->update([ + 'status' => 'cancelled', + 'admin_notes' => 'Retired during migration to server-owned reservations.', + 'updated_at' => now(), + ]); + + Schema::table('ptero_resource_reservations', function (Blueprint $table) { + $table->unique('active_cart_item_id', 'ptero_reservations_active_cart_item_unique'); + // Legacy releases could attach both browser and listener holds to one + // service. Keep this non-unique so the migration is deployable; the + // new bind path locks the cart hold and prevents new duplicates. + $table->index('service_id', 'ptero_reservations_service_idx'); + $table->index(['cart_id', 'status'], 'ptero_reservations_cart_status_idx'); + $table->index('server_extension_id', 'ptero_reservations_server_extension_idx'); + $table->index('configuration_fingerprint', 'ptero_reservations_fingerprint_idx'); + }); + } + + public function down(): void + { + Schema::table('ptero_resource_reservations', function (Blueprint $table) { + $table->dropUnique('ptero_reservations_active_cart_item_unique'); + $table->dropIndex('ptero_reservations_service_idx'); + $table->dropIndex('ptero_reservations_cart_status_idx'); + $table->dropIndex('ptero_reservations_server_extension_idx'); + $table->dropIndex('ptero_reservations_fingerprint_idx'); + $table->dropColumn([ + 'active_cart_item_id', + 'cart_id', + 'server_extension_id', + 'panel_identity', + 'product_id', + 'plan_id', + 'quantity', + 'currency_code', + 'configuration_fingerprint', + 'configuration_payload', + 'pricing_version', + 'formula_version', + 'provisioning_started_at', + 'provisioning_lease_id', + 'consumed_at', + 'last_provisioning_error', + ]); + }); + } +}; diff --git a/database/migrations/2026_07_25_000002_normalize_dynamic_option_keys.php b/database/migrations/2026_07_25_000002_normalize_dynamic_option_keys.php new file mode 100644 index 0000000..ab60729 --- /dev/null +++ b/database/migrations/2026_07_25_000002_normalize_dynamic_option_keys.php @@ -0,0 +1,98 @@ +join( + 'config_option_products', + 'config_option_products.config_option_id', + '=', + 'config_options.id' + ) + ->join('products', 'products.id', '=', 'config_option_products.product_id') + ->join('extensions', 'extensions.id', '=', 'products.server_id') + ->where('extensions.type', 'server') + ->where('extensions.extension', 'Pterodactyl') + ->whereNull('config_options.parent_id') + ->whereIn('config_options.type', ['dynamic_slider', 'select']) + ->distinct() + ->pluck('config_options.id'); + $options = DB::table('config_options') + ->whereIn('id', $optionIds) + ->get(['id', 'name', 'type', 'env_variable', 'metadata']); + + foreach ($options as $option) { + $metadata = is_string($option->metadata) + ? json_decode($option->metadata, true) ?? [] + : (array) $option->metadata; + $resourceType = strtolower((string) ($metadata['resource_type'] ?? '')); + $isResource = $option->type === 'dynamic_slider' + && in_array($resourceType, ['memory', 'cpu', 'disk'], true); + $isLocation = strtolower((string) $option->name) === 'location'; + + if (! $isResource && ! $isLocation) { + continue; + } + + $normalizedKey = $isResource ? $resourceType : 'location'; + DB::table('config_options') + ->where('id', $option->id) + ->update(['env_variable' => $normalizedKey]); + + if (! $isResource) { + continue; + } + + $productIds = DB::table('config_option_products') + ->join('products', 'products.id', '=', 'config_option_products.product_id') + ->join('extensions', 'extensions.id', '=', 'products.server_id') + ->where('config_option_products.config_option_id', $option->id) + ->where('extensions.type', 'server') + ->where('extensions.extension', 'Pterodactyl') + ->pluck('config_option_products.product_id'); + $serviceIds = DB::table('services') + ->whereIn('product_id', $productIds) + ->pluck('id'); + + foreach ($serviceIds as $serviceId) { + $upper = DB::table('properties') + ->where('model_type', Service::class) + ->where('model_id', $serviceId) + ->where('key', strtoupper($normalizedKey)) + ->first(); + + if ($upper === null) { + continue; + } + + $lowerExists = DB::table('properties') + ->where('model_type', Service::class) + ->where('model_id', $serviceId) + ->where('key', $normalizedKey) + ->exists(); + + if ($lowerExists) { + DB::table('properties')->where('id', $upper->id)->delete(); + } else { + DB::table('properties') + ->where('id', $upper->id) + ->update(['key' => $normalizedKey]); + } + } + } + }); + } + + public function down(): void + { + // Key normalization is intentionally irreversible. Reintroducing uppercase + // keys would make Pterodactyl ignore the selected slider values again. + } +}; diff --git a/routes/api.php b/routes/api.php index 5316d1d..54f734c 100644 --- a/routes/api.php +++ b/routes/api.php @@ -9,7 +9,6 @@ use Illuminate\Support\Facades\Route; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\AvailabilityController; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\PricingController; -use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\ReservationController; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\Admin\AdminCapacityController; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\Admin\AdminReservationController; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Middleware\EnsureUserIsAdmin; @@ -21,14 +20,6 @@ Route::get('/pricing/config/{productId}', [PricingController::class, 'getConfig']); }); -// Reservation endpoints — throttled (10 req/min) for checkout-retry burst tolerance without enabling abuse -Route::prefix('api/dynamic-pterodactyl')->middleware(['web', 'checkout', 'throttle:10,1'])->group(function () { - Route::post('/reservation', [ReservationController::class, 'create']); - Route::get('/reservation/{token}', [ReservationController::class, 'get']); - Route::delete('/reservation/{token}', [ReservationController::class, 'cancel']); - Route::post('/reservation/{token}/extend', [ReservationController::class, 'extend']); -}); - // Admin routes — session-based, gated by non-null role (matches User::canAccessPanel) Route::prefix('api/dynamic-pterodactyl/admin') ->middleware(['web', 'auth', EnsureUserIsAdmin::class, 'throttle:30,1']) diff --git a/tests/AGENTS.md b/tests/AGENTS.md index a7f59c7..f96157c 100644 --- a/tests/AGENTS.md +++ b/tests/AGENTS.md @@ -58,4 +58,4 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p - Do not broaden the database guard beyond `paymenter_test`, `:memory:`, or the internally generated `:temporary:` workflow. Never accept a caller-supplied SQLite path or named-memory URI. - Do not add live Pterodactyl network calls; fake panel HTTP explicitly and prevent strays when testing capacity reads. - Do not expose or assert full reservation tokens in audit payloads; assert `token_prefix` behavior. -- Current direct coverage gaps to watch: `CartItemCreatedListener`, `ServiceCreatedListener`, `PricingController::getConfig()`, and `AuditLogService` retrieval methods. +- Current direct coverage gaps to watch: full cart-listener database integration, `PricingController::getConfig()`, and `AuditLogService` retrieval methods. diff --git a/tests/Feature/AvailabilityApiTest.php b/tests/Feature/AvailabilityApiTest.php index e503e86..1e4eb09 100644 --- a/tests/Feature/AvailabilityApiTest.php +++ b/tests/Feature/AvailabilityApiTest.php @@ -20,7 +20,7 @@ protected function setUp(): void require __DIR__ . '/../../routes/api.php'; } - public function test_has_capacity_false_when_cpu_exhausted_but_memory_positive(): void + public function test_cpu_is_explicitly_not_enforced_as_capacity(): void { /** @var User $user */ $user = User::factory()->create(); @@ -36,12 +36,13 @@ public function test_has_capacity_false_when_cpu_exhausted_but_memory_positive() $response->assertOk()->assertJson([ 'success' => true, 'data' => [ - 'has_capacity' => false, + 'has_capacity' => true, 'resource_capacity' => [ 'memory' => true, - 'cpu' => false, + 'cpu' => null, 'disk' => true, ], + 'cpu_capacity_enforced' => false, ], ]); @@ -68,9 +69,10 @@ public function test_has_capacity_true_when_all_resources_positive(): void 'has_capacity' => true, 'resource_capacity' => [ 'memory' => true, - 'cpu' => true, + 'cpu' => null, 'disk' => true, ], + 'cpu_capacity_enforced' => false, ], ]); diff --git a/tests/Feature/ReservationApiTest.php b/tests/Feature/ReservationApiTest.php deleted file mode 100644 index 98d5054..0000000 --- a/tests/Feature/ReservationApiTest.php +++ /dev/null @@ -1,490 +0,0 @@ -withoutMiddleware(VerifyCsrfToken::class); - - $nodeSelectionService = $this->mock(NodeSelectionService::class); - $nodeSelectionService->shouldReceive('selectBestNode') - ->byDefault() - ->andReturn(['node_id' => 1, 'name' => 'Node 1']); - - $auditLogService = $this->mock(AuditLogService::class); - $auditLogService->shouldReceive('log')->byDefault()->andReturn(1); - } - - public function test_store_with_idempotency_key_returns_same_reservation_on_retry(): void - { - /** @var User $user */ - $user = User::withoutEvents(fn () => User::factory()->create()); - /** @var Product $product */ - $product = $this->createConfiguredProduct(); - $cartItemId = $this->createCartItemForUser($user, $product->id); - - $response = $this->actingAs($user)->withHeaders([ - 'Idempotency-Key' => 'idem-12345', - ])->postJson('/api/dynamic-pterodactyl/reservation', [ - 'product_id' => $product->id, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'cart_item_id' => $cartItemId, - ]); - - $retry = $this->actingAs($user)->withHeaders([ - 'Idempotency-Key' => 'idem-12345', - ])->postJson('/api/dynamic-pterodactyl/reservation', [ - 'product_id' => $product->id, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'cart_item_id' => $cartItemId, - ]); - - $response->assertOk()->assertJson(['success' => true]); - $retry->assertOk()->assertJson(['success' => true]); - - $this->assertSame($response->json('data.id'), $retry->json('data.id')); - $this->assertSame($response->json('data.token'), $retry->json('data.token')); - $this->assertEquals(1, ResourceReservation::query()->where('user_id', $user->id)->count()); - $this->assertDatabaseHas('ptero_resource_reservations', [ - 'user_id' => $user->id, - 'idempotency_key' => 'idem-12345', - 'status' => 'pending', - ]); - } - - public function test_store_without_idempotency_key_creates_fresh_each_time(): void - { - /** @var User $user */ - $user = User::withoutEvents(fn () => User::factory()->create()); - /** @var Product $product */ - $product = $this->createConfiguredProduct(); - $firstCartItemId = $this->createCartItemForUser($user, $product->id); - $secondCartItemId = $this->createCartItemForUser($user, $product->id); - - $first = $this->actingAs($user)->postJson('/api/dynamic-pterodactyl/reservation', [ - 'product_id' => $product->id, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'cart_item_id' => $firstCartItemId, - ]); - - $second = $this->actingAs($user)->postJson('/api/dynamic-pterodactyl/reservation', [ - 'product_id' => $product->id, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'cart_item_id' => $secondCartItemId, - ]); - - $first->assertOk()->assertJson(['success' => true]); - $second->assertOk()->assertJson(['success' => true]); - - $this->assertNotSame($first->json('data.token'), $second->json('data.token')); - $this->assertEquals(2, ResourceReservation::query()->where('user_id', $user->id)->count()); - } - - public function test_store_rejects_invalid_idempotency_key(): void - { - /** @var User $user */ - $user = User::withoutEvents(fn () => User::factory()->create()); - /** @var Product $product */ - $product = $this->createConfiguredProduct(); - $cartItemId = $this->createCartItemForUser($user, $product->id); - - $response = $this->actingAs($user)->withHeaders([ - 'Idempotency-Key' => 'bad key', - ])->postJson('/api/dynamic-pterodactyl/reservation', [ - 'product_id' => $product->id, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'cart_item_id' => $cartItemId, - ]); - - $response->assertStatus(422); - $response->assertJsonValidationErrors('idempotency_key'); - } - - public function test_store_rejects_unconfigured_product(): void - { - /** @var User $user */ - $user = User::withoutEvents(fn () => User::factory()->create()); - /** @var Product $product */ - $product = Product::factory()->create(); - $cartItemId = $this->createCartItemForUser($user, $product->id); - - $response = $this->actingAs($user)->postJson('/api/dynamic-pterodactyl/reservation', [ - 'product_id' => $product->id, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'cart_item_id' => $cartItemId, - ]); - - $response->assertStatus(422); - $response->assertJsonValidationErrors('product_id'); - } - - public function test_store_rejects_out_of_bounds_memory(): void - { - /** @var User $user */ - $user = User::withoutEvents(fn () => User::factory()->create()); - /** @var Product $product */ - $product = $this->createConfiguredProduct(); - $cartItemId = $this->createCartItemForUser($user, $product->id); - - $response = $this->actingAs($user)->postJson('/api/dynamic-pterodactyl/reservation', [ - 'product_id' => $product->id, - 'location_id' => 1, - 'memory' => 99999, - 'cpu' => 200, - 'disk' => 51200, - 'cart_item_id' => $cartItemId, - ]); - - $response->assertStatus(422); - $response->assertJsonValidationErrors('memory'); - } - - public function test_user_cannot_create_reservation_against_anothers_cart_item(): void - { - /** @var User $owner */ - $owner = User::withoutEvents(fn () => User::factory()->create()); - /** @var User $stranger */ - $stranger = User::withoutEvents(fn () => User::factory()->create()); - /** @var Product $product */ - $product = $this->createConfiguredProduct(); - $cartItemId = $this->createCartItemForUser($owner, $product->id); - - $response = $this->actingAs($stranger)->postJson('/api/dynamic-pterodactyl/reservation', [ - 'product_id' => $product->id, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'cart_item_id' => $cartItemId, - ]); - - $response->assertForbidden(); - } - - public function test_user_can_create_reservation_against_own_cart_item(): void - { - /** @var User $user */ - $user = User::withoutEvents(fn () => User::factory()->create()); - /** @var Product $product */ - $product = $this->createConfiguredProduct(); - $cartItemId = $this->createCartItemForUser($user, $product->id); - - $response = $this->actingAs($user)->postJson('/api/dynamic-pterodactyl/reservation', [ - 'product_id' => $product->id, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'cart_item_id' => $cartItemId, - ]); - - $response->assertOk()->assertJson(['success' => true]); - $this->assertDatabaseHas('ptero_resource_reservations', [ - 'user_id' => $user->id, - 'cart_item_id' => $cartItemId, - 'status' => 'pending', - ]); - } - - public function test_guest_can_create_reservation_without_cart_item_id(): void - { - /** @var Product $product */ - $product = $this->createConfiguredProduct(); - - $response = $this->postJson('/api/dynamic-pterodactyl/reservation', [ - 'product_id' => $product->id, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - ]); - - $response->assertOk()->assertJson(['success' => true]); - $this->assertNotNull($response->json('data.token')); - $this->assertDatabaseHas('ptero_resource_reservations', [ - 'user_id' => null, - 'cart_item_id' => null, - 'location_id' => 1, - 'status' => 'pending', - ]); - } - - public function test_guest_reservation_throttled_by_ip(): void - { - /** @var Product $product */ - $product = $this->createConfiguredProduct(); - - $payload = [ - 'product_id' => $product->id, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - ]; - - for ($i = 1; $i <= 10; $i++) { - $this->withServerVariables(['REMOTE_ADDR' => '203.0.113.10']) - ->postJson('/api/dynamic-pterodactyl/reservation', $payload) - ->assertOk(); - } - - $this->withServerVariables(['REMOTE_ADDR' => '203.0.113.10']) - ->postJson('/api/dynamic-pterodactyl/reservation', $payload) - ->assertStatus(429); - } - - public function test_reservation_requires_valid_location_id(): void - { - /** @var Product $product */ - $product = $this->createConfiguredProduct(); - - $response = $this->postJson('/api/dynamic-pterodactyl/reservation', [ - 'product_id' => $product->id, - 'location_id' => 999, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - ]); - - $response->assertStatus(422); - $response->assertJsonValidationErrors('location_id'); - } - - public function test_admin_can_view_other_users_reservation(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - $admin = $this->makeAdminUser(); - $reservation = $this->makeReservation($owner); - - $this->actingAs($admin) - ->getJson('/api/dynamic-pterodactyl/reservation/' . $reservation->token) - ->assertOk() - ->assertJson(['success' => true]); - } - - public function test_admin_can_cancel_other_users_reservation(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - $admin = $this->makeAdminUser(); - $reservation = $this->makeReservation($owner); - - $this->actingAs($admin) - ->deleteJson('/api/dynamic-pterodactyl/reservation/' . $reservation->token) - ->assertOk() - ->assertJson(['success' => true]); - - $this->assertDatabaseHas('ptero_resource_reservations', [ - 'id' => $reservation->id, - 'status' => 'cancelled', - ]); - } - - public function test_admin_can_extend_other_users_reservation(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - $admin = $this->makeAdminUser(); - $reservation = $this->makeReservation($owner); - - $this->actingAs($admin) - ->postJson('/api/dynamic-pterodactyl/reservation/' . $reservation->token . '/extend', ['minutes' => 20]) - ->assertOk() - ->assertJson(['success' => true]); - } - - public function test_stranger_cannot_view_other_users_reservation(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - $stranger = User::withoutEvents(fn () => User::factory()->create()); - $reservation = $this->makeReservation($owner); - - $this->actingAs($stranger) - ->getJson('/api/dynamic-pterodactyl/reservation/' . $reservation->token) - ->assertForbidden(); - } - - public function test_stranger_cannot_cancel_other_users_reservation(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - $stranger = User::withoutEvents(fn () => User::factory()->create()); - $reservation = $this->makeReservation($owner); - - $this->actingAs($stranger) - ->deleteJson('/api/dynamic-pterodactyl/reservation/' . $reservation->token) - ->assertForbidden(); - } - - public function test_stranger_cannot_extend_other_users_reservation(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - $stranger = User::withoutEvents(fn () => User::factory()->create()); - $reservation = $this->makeReservation($owner); - - $this->actingAs($stranger) - ->postJson('/api/dynamic-pterodactyl/reservation/' . $reservation->token . '/extend', ['minutes' => 20]) - ->assertForbidden(); - } - - public function test_owner_can_view_own_reservation(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - $reservation = $this->makeReservation($owner); - - $this->actingAs($owner) - ->getJson('/api/dynamic-pterodactyl/reservation/' . $reservation->token) - ->assertOk() - ->assertJson(['success' => true]); - } - - public function test_reservation_create_throttles_at_10_per_minute(): void - { - $user = User::withoutEvents(fn () => User::factory()->create()); - /** @var Product $product */ - $product = Product::factory()->create(); - $cartItemId = $this->createCartItemForUser($user, $product->id); - - $payload = [ - 'product_id' => $product->id, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'cart_item_id' => $cartItemId, - ]; - - for ($i = 1; $i <= 10; $i++) { - $this->actingAs($user) - ->postJson('/api/dynamic-pterodactyl/reservation', $payload) - ->assertStatus(422); - } - - $this->actingAs($user) - ->postJson('/api/dynamic-pterodactyl/reservation', $payload) - ->assertStatus(429); - } - - private function createConfiguredProduct(): Product - { - /** @var Product $product */ - $product = Product::factory()->create(); - - $product->settings()->create([ - 'key' => 'location_ids', - 'value' => json_encode([1]), - 'type' => 'array', - ]); - - foreach ([ - 'memory' => ['name' => 'Memory', 'min' => 1024, 'max' => 8192, 'step' => 1024, 'unit' => 'MB'], - 'cpu' => ['name' => 'CPU', 'min' => 100, 'max' => 400, 'step' => 100, 'unit' => '%'], - 'disk' => ['name' => 'Disk', 'min' => 10240, 'max' => 102400, 'step' => 10240, 'unit' => 'MB'], - ] as $resourceType => $slider) { - $optionId = DB::table('config_options')->insertGetId([ - 'name' => $slider['name'], - 'type' => 'dynamic_slider', - 'sort' => 0, - 'hidden' => false, - 'upgradable' => true, - 'metadata' => json_encode([ - 'resource_type' => $resourceType, - 'min' => $slider['min'], - 'max' => $slider['max'], - 'step' => $slider['step'], - 'default' => $slider['min'], - 'unit' => $slider['unit'], - 'display_unit' => $slider['unit'], - 'display_divisor' => 1, - 'pricing' => ['model' => 'linear', 'rate_per_unit' => 1], - ]), - 'created_at' => now(), - 'updated_at' => now(), - ]); - - DB::table('config_option_products')->insert([ - 'product_id' => $product->id, - 'config_option_id' => $optionId, - ]); - } - - return $product; - } - - private function makeAdminUser(): User - { - $role = Role::firstOrCreate(['name' => 'Admin']); - - return User::withoutEvents(fn () => User::factory()->create(['role_id' => $role->id])); - } - - private function makeReservation(User $user, array $attributes = []): ResourceReservation - { - return ResourceReservation::create(array_merge([ - 'token' => (string) Str::random(64), - 'user_id' => $user->id, - 'node_id' => 1, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'calculated_price' => 9.99, - 'pricing_breakdown' => [], - 'status' => 'pending', - 'expires_at' => now()->addMinutes(15), - ], $attributes)); - } - - private function createCartItemForUser(User $user, int $productId): int - { - $cartId = DB::table('carts')->insertGetId([ - 'ulid' => (string) Str::ulid(), - 'user_id' => $user->id, - 'currency_code' => 'USD', - 'created_at' => now(), - 'updated_at' => now(), - ]); - - return DB::table('cart_items')->insertGetId([ - 'cart_id' => $cartId, - 'product_id' => $productId, - 'quantity' => 1, - 'created_at' => now(), - 'updated_at' => now(), - ]); - } -} diff --git a/tests/Unit/CartItemDeletedListenerTest.php b/tests/Unit/CartItemDeletedListenerTest.php index 769285c..7679a96 100644 --- a/tests/Unit/CartItemDeletedListenerTest.php +++ b/tests/Unit/CartItemDeletedListenerTest.php @@ -2,9 +2,10 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; -use App\Events\CartItem\Deleted; +use App\Events\CartItem\Deleting; use App\Models\CartItem; use Illuminate\Support\Facades\Log; +use Mockery; use Paymenter\Extensions\Others\DynamicPterodactyl\Listeners\CartItemDeletedListener; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; @@ -13,123 +14,45 @@ class CartItemDeletedListenerTest extends LaravelTestCase { protected function tearDown(): void { - \Mockery::close(); - + Mockery::close(); parent::tearDown(); } - public function test_no_token_returns_early_without_cancelling(): void - { - $reservationService = \Mockery::mock(ReservationService::class); - $reservationService->shouldNotReceive('cancel'); - $this->app->instance(ReservationService::class, $reservationService); - - $listener = new CartItemDeletedListener; - $listener->handle(new Deleted($this->makeCartItem())); - - $this->addToAssertionCount(1); - } - - public function test_skip_checkout_path_does_not_cancel_and_logs_debug(): void + public function test_cart_item_deletion_cancels_by_relationship_without_a_token(): void { - $token = 'checkout_token_123'; - $propertyQuery = \Mockery::mock(); - $propertyQuery->shouldReceive('where')->once()->with('value', $token)->andReturnSelf(); - - $serviceQuery = \Mockery::mock(); - $serviceQuery->shouldReceive('exists')->once()->andReturn(true); - - $serviceModel = \Mockery::mock('alias:App\\Models\\Service'); - $serviceModel->shouldReceive('whereHas') + $reservationService = Mockery::mock(ReservationService::class); + $reservationService->shouldReceive('cancelForCartItem') ->once() - ->with('properties', \Mockery::on(function ($closure) use ($propertyQuery) { - $propertyQuery->shouldReceive('where')->once()->with('key', '_reservation_token')->andReturn($propertyQuery); - $closure($propertyQuery); - - return true; - })) - ->andReturn($serviceQuery); - - $reservationService = \Mockery::mock(ReservationService::class); - $reservationService->shouldNotReceive('cancel'); - $this->app->instance(ReservationService::class, $reservationService); - - Log::shouldReceive('debug') - ->once() - ->with('Skipping reservation cancel: cart item consumed by checkout', \Mockery::on(function ($context) use ($token) { - return $context['cart_item_id'] === 1 - && $context['reservation_token'] === substr($token, 0, 8) . '...'; - })); - - $listener = new CartItemDeletedListener; - $listener->handle(new Deleted($this->makeCartItem($token))); - - $this->addToAssertionCount(1); - } - - public function test_abandonment_path_cancels_reservation(): void - { - $token = 'abandon_token_123'; - - $serviceQuery = \Mockery::mock(); - $serviceQuery->shouldReceive('exists')->once()->andReturn(false); - - $serviceModel = \Mockery::mock('alias:App\\Models\\Service'); - $serviceModel->shouldReceive('whereHas')->once()->andReturn($serviceQuery); - - $reservationService = \Mockery::mock(ReservationService::class); - $reservationService->shouldReceive('cancel')->once()->with($token, null, 'cart_deleted', null); - $this->app->instance(ReservationService::class, $reservationService); + ->with(42) + ->andReturn(true); Log::shouldReceive('info') ->once() - ->with('Cancelled reservation for deleted cart item', \Mockery::on(function ($context) use ($token) { - return $context['cart_item_id'] === 1 - && $context['reservation_token'] === substr($token, 0, 8) . '...'; - })); + ->with('Cancelled capacity reservation for removed cart item', [ + 'cart_item_id' => 42, + ]); - $listener = new CartItemDeletedListener; - $listener->handle(new Deleted($this->makeCartItem($token))); + $cartItem = new CartItem; + $cartItem->id = 42; - $this->addToAssertionCount(1); + (new CartItemDeletedListener($reservationService)) + ->handle(new Deleting($cartItem)); } - public function test_exception_path_logs_error_without_rethrowing(): void + public function test_bound_or_missing_hold_needs_no_cancellation_log(): void { - $token = 'exception_token_123'; - - $serviceQuery = \Mockery::mock(); - $serviceQuery->shouldReceive('exists')->once()->andReturn(false); - - $serviceModel = \Mockery::mock('alias:App\\Models\\Service'); - $serviceModel->shouldReceive('whereHas')->once()->andReturn($serviceQuery); - - $reservationService = \Mockery::mock(ReservationService::class); - $reservationService->shouldReceive('cancel') - ->once() - ->with($token, null, 'cart_deleted', null) - ->andThrow(new \RuntimeException('boom')); - $this->app->instance(ReservationService::class, $reservationService); - - Log::shouldReceive('error') + $reservationService = Mockery::mock(ReservationService::class); + $reservationService->shouldReceive('cancelForCartItem') ->once() - ->with('Failed to cancel reservation', \Mockery::on(function ($context) use ($token) { - return $context['token'] === substr($token, 0, 8) . '...' - && $context['error'] === 'boom'; - })); + ->with(42) + ->andReturn(false); - $listener = new CartItemDeletedListener; - $listener->handle(new Deleted($this->makeCartItem($token))); + Log::shouldReceive('info')->never(); - $this->addToAssertionCount(1); - } - - private function makeCartItem(?string $token = null): CartItem - { $cartItem = new CartItem; - $cartItem->id = 1; - $cartItem->checkout_config = $token ? ['_reservation_token' => $token] : []; + $cartItem->id = 42; - return $cartItem; + (new CartItemDeletedListener($reservationService)) + ->handle(new Deleting($cartItem)); } } diff --git a/tests/Unit/InvoicePaidListenerTest.php b/tests/Unit/InvoicePaidListenerTest.php deleted file mode 100644 index 1a248aa..0000000 --- a/tests/Unit/InvoicePaidListenerTest.php +++ /dev/null @@ -1,131 +0,0 @@ - 50, - 'node_id' => 7, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - ]; - - $reservationService = Mockery::mock(ReservationService::class); - $reservationService->shouldReceive('getByToken')->once()->with($token)->andReturn($reservation); - $this->app->instance(ReservationService::class, $reservationService); - - $resourceService = Mockery::mock(ResourceCalculationService::class); - $resourceService->shouldReceive('verifyAvailability')->once()->with(7, [ - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - ], $token)->andReturn(false); - $this->app->instance(ResourceCalculationService::class, $resourceService); - - $alertService = Mockery::mock(AlertService::class); - $alertService->shouldReceive('notifyShortfall')->once()->with( - 10, - 20, - ['memory' => 4096, 'cpu' => 200, 'disk' => 51200], - 'insufficient_resources' - ); - $this->app->instance(AlertService::class, $alertService); - - $listener = new InvoicePaidListener; - $listener->handle(new Paid($this->makeInvoiceEventData(serviceId: 10, invoiceId: 20, token: $token))); - - $this->addToAssertionCount(1); - } - - public function test_state_drift_triggers_notification(): void - { - $token = 'state-drift-token'; - $reservation = (object) [ - 'id' => 51, - 'node_id' => 8, - 'memory' => 2048, - 'cpu' => 150, - 'disk' => 25600, - ]; - $current = (object) ['status' => 'expired']; - - $reservationService = Mockery::mock(ReservationService::class); - $reservationService->shouldReceive('getByToken')->once()->with($token)->andReturn($reservation); - $reservationService->shouldReceive('confirm')->once()->with($token, 11, null)->andReturn(false); - $reservationService->shouldReceive('getByToken')->once()->with($token)->andReturn($current); - $this->app->instance(ReservationService::class, $reservationService); - - $resourceService = Mockery::mock(ResourceCalculationService::class); - $resourceService->shouldReceive('verifyAvailability')->once()->with(8, [ - 'memory' => 2048, - 'cpu' => 150, - 'disk' => 25600, - ], $token)->andReturn(true); - $this->app->instance(ResourceCalculationService::class, $resourceService); - - $alertService = Mockery::mock(AlertService::class); - $alertService->shouldReceive('notifyShortfall')->once()->with( - 11, - 21, - ['memory' => 2048, 'cpu' => 150, 'disk' => 25600], - 'state_drift:expired' - ); - $this->app->instance(AlertService::class, $alertService); - - $listener = new InvoicePaidListener; - $listener->handle(new Paid($this->makeInvoiceEventData(serviceId: 11, invoiceId: 21, token: $token))); - - $this->addToAssertionCount(1); - } - - private function makeInvoiceEventData(int $serviceId, int $invoiceId, string $token): Invoice - { - $propertyQuery = Mockery::mock(); - $propertyQuery->shouldReceive('where')->once()->with('key', '_reservation_token')->andReturnSelf(); - $propertyQuery->shouldReceive('value')->once()->with('value')->andReturn($token); - - $service = new class($propertyQuery) extends Service - { - public function __construct(private object $propertyQuery) {} - - public function properties() - { - return $this->propertyQuery; - } - }; - $service->id = $serviceId; - - $item = new InvoiceItem; - $item->reference_type = Service::class; - $item->setRelation('reference', $service); - - $invoice = new Invoice; - $invoice->id = $invoiceId; - $invoice->setRelation('items', collect([$item])); - - return $invoice; - } -} diff --git a/tests/Unit/NodeSelectionServiceTest.php b/tests/Unit/NodeSelectionServiceTest.php index 4b9c94a..03bc558 100644 --- a/tests/Unit/NodeSelectionServiceTest.php +++ b/tests/Unit/NodeSelectionServiceTest.php @@ -32,7 +32,7 @@ protected function tearDown(): void public function test_selects_node_with_most_headroom(): void { $this->mockResourceService->shouldReceive('getLocationAvailability') - ->with(1) + ->with(1, null) ->andReturn([ 'nodes' => [ $this->createNodeData(1, 'Node 1', [ @@ -75,7 +75,7 @@ public function test_selects_node_with_most_headroom(): void public function test_skips_nodes_in_maintenance(): void { $this->mockResourceService->shouldReceive('getLocationAvailability') - ->with(1) + ->with(1, null) ->andReturn([ 'nodes' => [ $this->createNodeData(1, 'Node 1 (Maint)', [ @@ -117,7 +117,7 @@ public function test_skips_nodes_in_maintenance(): void public function test_skips_nodes_with_insufficient_memory(): void { $this->mockResourceService->shouldReceive('getLocationAvailability') - ->with(1) + ->with(1, null) ->andReturn([ 'nodes' => [ $this->createNodeData(1, 'Low Memory Node', [ @@ -154,12 +154,12 @@ public function test_skips_nodes_with_insufficient_memory(): void } /** - * Test that nodes with insufficient CPU are skipped. + * CPU limits do not affect node selection without authoritative inventory. */ - public function test_skips_nodes_with_insufficient_cpu(): void + public function test_cpu_is_not_treated_as_hard_capacity(): void { $this->mockResourceService->shouldReceive('getLocationAvailability') - ->with(1) + ->with(1, null) ->andReturn([ 'nodes' => [ $this->createNodeData(1, 'Low CPU Node', [ @@ -191,7 +191,7 @@ public function test_skips_nodes_with_insufficient_cpu(): void ]); $this->assertNotNull($result); - $this->assertEquals(2, $result['node_id']); + $this->assertEquals(1, $result['node_id']); } /** @@ -200,7 +200,7 @@ public function test_skips_nodes_with_insufficient_cpu(): void public function test_skips_nodes_with_insufficient_disk(): void { $this->mockResourceService->shouldReceive('getLocationAvailability') - ->with(1) + ->with(1, null) ->andReturn([ 'nodes' => [ $this->createNodeData(1, 'Low Disk Node', [ @@ -241,7 +241,7 @@ public function test_skips_nodes_with_insufficient_disk(): void public function test_returns_null_when_no_nodes_available(): void { $this->mockResourceService->shouldReceive('getLocationAvailability') - ->with(1) + ->with(1, null) ->andReturn([ 'nodes' => [ $this->createNodeData(1, 'Full Node', [ @@ -272,7 +272,7 @@ public function test_returns_null_when_no_nodes_available(): void public function test_weighted_scoring_prefers_memory_headroom(): void { $this->mockResourceService->shouldReceive('getLocationAvailability') - ->with(1) + ->with(1, null) ->andReturn([ 'nodes' => [ // Node 1: Better disk/cpu but less memory headroom @@ -322,7 +322,7 @@ public function test_get_max_available_returns_location_max(): void ]; $this->mockResourceService->shouldReceive('getLocationAvailability') - ->with(1) + ->with(1, null) ->andReturn([ 'location_id' => 1, 'nodes' => [], @@ -371,7 +371,7 @@ public function test_get_max_available_rejects_incomplete_preloaded_snapshot(): public function test_empty_nodes_returns_null(): void { $this->mockResourceService->shouldReceive('getLocationAvailability') - ->with(1) + ->with(1, null) ->andReturn([ 'nodes' => [], 'max_available' => [], diff --git a/tests/Unit/ReservationConfigurationServiceTest.php b/tests/Unit/ReservationConfigurationServiceTest.php new file mode 100644 index 0000000..62ecf8d --- /dev/null +++ b/tests/Unit/ReservationConfigurationServiceTest.php @@ -0,0 +1,68 @@ + 10, + 'resources' => ['memory' => 4096, 'cpu' => 200, 'disk' => 51200], + 'node_id' => 3, + ]; + $right = [ + 'node_id' => 3, + 'resources' => ['disk' => 51200, 'cpu' => 200, 'memory' => 4096], + 'product_id' => 10, + ]; + + $this->assertSame($service->fingerprint($left), $service->fingerprint($right)); + } + + public function test_resource_or_node_change_changes_fingerprint(): void + { + $service = new ReservationConfigurationService; + $snapshot = [ + 'customer_id' => 30, + 'cart_id' => 1, + 'server_extension_id' => 5, + 'panel_identity' => str_repeat('c', 64), + 'product_id' => 10, + 'plan_id' => 20, + 'quantity' => 1, + 'currency_code' => 'AUD', + 'location_id' => 2, + 'resources' => ['memory' => 4096, 'cpu' => 200, 'disk' => 51200], + 'calculated_price' => 25.00, + 'pricing_version' => str_repeat('a', 64), + 'formula_version' => ReservationConfigurationService::FORMULA_VERSION, + 'config_options' => [], + ]; + + $original = $service->fingerprint($service->withNode($snapshot, 3)); + + $moreMemory = $snapshot; + $moreMemory['resources']['memory'] = 8192; + + $this->assertNotSame( + $original, + $service->fingerprint($service->withNode($moreMemory, 3)) + ); + $this->assertNotSame( + $original, + $service->fingerprint($service->withNode($snapshot, 4)) + ); + + $guestPayload = $service->withNode(array_replace($snapshot, ['customer_id' => null]), 3); + $this->assertNotSame( + $service->fingerprint($guestPayload), + $service->fingerprint($service->withCustomer($guestPayload, 30)) + ); + } +} diff --git a/tests/Unit/ReservationServiceTest.php b/tests/Unit/ReservationServiceTest.php index 482546a..5f6d36f 100644 --- a/tests/Unit/ReservationServiceTest.php +++ b/tests/Unit/ReservationServiceTest.php @@ -2,19 +2,14 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; +use App\Models\Service; use App\Models\User; - -use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Config; -use Illuminate\Support\Facades\Gate; -use Illuminate\Support\Facades\Log; use Mockery; -use Paymenter\Extensions\Others\DynamicPterodactyl\Models\ResourceReservation; -use Paymenter\Extensions\Others\DynamicPterodactyl\Policies\ResourceReservationPolicy; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AuditLogService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\NodeSelectionService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationConfigurationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; @@ -22,21 +17,21 @@ class ReservationServiceTest extends LaravelTestCase { use DatabaseTransactions; - private $mockNodeService; + private NodeSelectionService $nodeService; - private $mockAuditService; + private ReservationConfigurationService $configurationService; protected function setUp(): void { parent::setUp(); - Config::set('settings.debug', false); - Gate::policy(ResourceReservation::class, ResourceReservationPolicy::class); - - $this->mockNodeService = Mockery::mock(NodeSelectionService::class); - $this->mockAuditService = Mockery::mock(AuditLogService::class); + $this->nodeService = Mockery::mock(NodeSelectionService::class); + $this->configurationService = Mockery::mock(ReservationConfigurationService::class) + ->makePartial(); - $this->app->instance(AuditLogService::class, $this->mockAuditService); + $audit = Mockery::mock(AuditLogService::class); + $audit->shouldReceive('log')->zeroOrMoreTimes(); + $this->app->instance(AuditLogService::class, $audit); } protected function tearDown(): void @@ -45,519 +40,174 @@ protected function tearDown(): void parent::tearDown(); } - /** - * Create ReservationService with mocked dependencies. - * Uses reflection to bypass constructor ExtensionHelper call. - */ - private function createService(): ReservationService - { - $reflection = new \ReflectionClass(ReservationService::class); - $service = $reflection->newInstanceWithoutConstructor(); - - foreach ([ - 'nodeService' => $this->mockNodeService, - 'ttlMinutes' => 15, - ] as $property => $value) { - $instanceProperty = $reflection->getProperty($property); - $instanceProperty->setAccessible(true); - $instanceProperty->setValue($service, $value); - } - - return $service; - } - - public function test_safeAudit_logs_warning_on_failure(): void - { - $this->mockAuditService->shouldReceive('log') - ->once() - ->with('created', 'reservation', 99, ['token_prefix' => 'deadbeef...']) - ->andThrow(new \RuntimeException('audit backend unavailable')); - - Log::shouldReceive('warning') - ->once() - ->with('extension audit write failed', Mockery::on(function (array $context) { - return $context['action'] === 'created' - && $context['entity_type'] === 'reservation' - && $context['entity_id'] === 99 - && $context['error'] === 'audit backend unavailable'; - })); - Log::shouldReceive('error')->zeroOrMoreTimes(); - - $service = new class - { - use \Paymenter\Extensions\Others\DynamicPterodactyl\Services\Concerns\AuditsExtensionActions; - - public function writeAudit(): void - { - $this->safeAudit('created', 'reservation', 99, ['token_prefix' => 'deadbeef...']); - } - }; - - $service->writeAudit(); - - $this->addToAssertionCount(1); - } - - /** - * Test that confirm updates status to confirmed. - */ - public function test_confirm_updates_status(): void - { - $token = 'test_token_123'; - $serviceId = 42; - - DB::shouldReceive('table') - ->with('ptero_resource_reservations') - ->andReturnSelf(); - DB::shouldReceive('where') - ->with('token', $token) - ->andReturnSelf(); - DB::shouldReceive('where') - ->with('status', 'pending') - ->andReturnSelf(); - DB::shouldReceive('where') - ->with('expires_at', '>', Mockery::any()) - ->andReturnSelf(); - DB::shouldReceive('first')->once()->andReturn((object) ['id' => 99, 'token' => $token]); - DB::shouldReceive('update') - ->with(Mockery::on(function ($data) use ($serviceId) { - return $data['status'] === 'confirmed' - && $data['service_id'] === $serviceId - && isset($data['updated_at']); - })) - ->andReturn(1); - $this->mockAuditService->shouldReceive('log') - ->once() - ->with('reservation_confirmed', 'resource_reservation', 99, Mockery::on(fn ($ctx) => $ctx['token_prefix'] === substr($token, 0, 8) - && $ctx['service_id'] === $serviceId - && array_key_exists('node_id', $ctx) - && $ctx['node_id'] === null)) - ->andReturn(1); - - $service = $this->createService(); - $result = $service->confirm($token, $serviceId); - - $this->assertTrue($result); - } - - /** - * Test that confirm returns false for non-existent token. - */ - public function test_confirm_returns_false_for_nonexistent_token(): void - { - DB::shouldReceive('table') - ->with('ptero_resource_reservations') - ->andReturnSelf(); - DB::shouldReceive('where')->times(4)->andReturnSelf(); - DB::shouldReceive('first')->once()->andReturn(null); - DB::shouldReceive('update')->andReturn(0); - - $service = $this->createService(); - $result = $service->confirm('nonexistent', 1); - - $this->assertFalse($result); - } - - /** - * Test that expired reservations cannot be confirmed. - */ - public function test_expired_reservation_cannot_be_confirmed(): void + public function test_guest_holds_transfer_with_cart_ownership(): void { - $token = 'expired_token_123'; - - DB::shouldReceive('table') - ->with('ptero_resource_reservations') - ->andReturnSelf(); - DB::shouldReceive('where') - ->with('token', $token) - ->andReturnSelf(); - DB::shouldReceive('where') - ->with('status', 'pending') - ->andReturnSelf(); - DB::shouldReceive('where') - ->with('expires_at', '>', Mockery::any()) - ->andReturnSelf(); - DB::shouldReceive('first')->once()->andReturn((object) ['id' => 5, 'token' => $token]); - DB::shouldReceive('update')->andReturn(0); - - $service = $this->createService(); - $result = $service->confirm($token, 1); - - $this->assertFalse($result); - } + $user = User::withoutEvents(fn () => User::factory()->create()); + $this->insertReservation(cartId: 71, userId: null); - /** - * Test that cancel updates status to cancelled. - */ - public function test_cancel_updates_status(): void - { - $token = 'test_token_123'; + $updated = $this->service()->transferCartOwnership(71, $user->id); - $mockReservation = (object) [ - 'id' => 1, - 'token' => $token, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, + $this->assertSame(1, $updated); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'cart_id' => 71, + 'user_id' => $user->id, 'status' => 'pending', - ]; - - // First call for getByToken - DB::shouldReceive('table') - ->with('ptero_resource_reservations') - ->andReturnSelf(); - DB::shouldReceive('where') - ->with('token', $token) - ->andReturnSelf(); - DB::shouldReceive('first') - ->once() - ->andReturn($mockReservation); - - // Second call for update - DB::shouldReceive('where') - ->with('status', 'pending') - ->andReturnSelf(); - DB::shouldReceive('update') - ->with(Mockery::on(function ($data) { - return $data['status'] === 'cancelled' - && isset($data['updated_at']); - })) - ->andReturn(1); - $this->mockAuditService->shouldReceive('log') - ->once() - ->with('reservation_cancelled', 'resource_reservation', 1, Mockery::on(fn ($ctx) => $ctx['token_prefix'] === substr($token, 0, 8) - && array_key_exists('node_id', $ctx) - && $ctx['node_id'] === null)) - ->andReturn(1); - - $service = $this->createService(); - $result = $service->cancel($token); - - $this->assertTrue($result); + ]); + $reservation = DB::table('ptero_resource_reservations')->where('cart_id', 71)->first(); + $payload = json_decode($reservation->configuration_payload, true, 512, JSON_THROW_ON_ERROR); + $this->assertSame($user->id, $payload['customer_id']); + $this->assertSame( + $this->configurationService->fingerprint($payload), + $reservation->configuration_fingerprint + ); } - /** - * Test that cancel returns false for non-existent token. - */ - public function test_cancel_returns_false_for_nonexistent_token(): void + public function test_begin_keeps_hold_pending_until_complete_consumes_it(): void { - DB::shouldReceive('table') - ->with('ptero_resource_reservations') - ->andReturnSelf(); - DB::shouldReceive('where')->andReturnSelf(); - DB::shouldReceive('first')->andReturn(null); - - $service = $this->createService(); - $result = $service->cancel('nonexistent'); + $service = $this->makeService(); + $reservationId = $this->insertReservation(serviceId: $service->id, userId: $service->user_id); - $this->assertFalse($result); - } - - /** - * Test that cleanup expired marks pending reservations as expired. - */ - public function test_cleanup_expired_marks_pending_as_expired(): void - { - DB::shouldReceive('table') - ->with('ptero_resource_reservations') - ->andReturnSelf(); - DB::shouldReceive('where') - ->with('status', 'pending') - ->andReturnSelf(); - DB::shouldReceive('where') - ->with('expires_at', '<', Mockery::any()) - ->andReturnSelf(); - DB::shouldReceive('update') - ->with(Mockery::on(function ($data) { - return $data['status'] === 'expired' - && isset($data['updated_at']); - })) - ->andReturn(5); - $this->mockAuditService->shouldReceive('log') + $this->configurationService->shouldReceive('assertServiceMatches') ->once() - ->with('reservations_expired_batch', 'resource_reservation', 0, Mockery::on(fn ($ctx) => $ctx['count'] === 5 && isset($ctx['run_at']))) - ->andReturn(1); + ->with($service, Mockery::on(fn ($row) => (int) $row->id === $reservationId)); - $service = $this->createService(); - $result = $service->cleanupExpired(); + $context = $this->service()->beginProvisioning($service); - $this->assertEquals(5, $result); - } - - /** - * Test getByToken returns reservation. - */ - public function test_get_by_token_returns_reservation(): void - { - $token = 'test_token_123'; - $expected = (object) [ - 'id' => 1, - 'token' => $token, - 'status' => 'pending', - ]; - - DB::shouldReceive('table') - ->with('ptero_resource_reservations') - ->andReturnSelf(); - DB::shouldReceive('where') - ->with('token', $token) - ->andReturnSelf(); - DB::shouldReceive('first') - ->andReturn($expected); - - $service = $this->createService(); - $result = $service->getByToken($token); - - $this->assertEquals($expected, $result); - } - - /** - * Test getByCartItem returns pending reservation. - */ - public function test_get_by_cart_item_returns_pending_reservation(): void - { - $cartItemId = 42; - $expected = (object) [ - 'id' => 1, - 'cart_item_id' => $cartItemId, + $this->assertSame(4, $context['node_id']); + $this->assertFalse($context['already_consumed']); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, 'status' => 'pending', - ]; - - DB::shouldReceive('table') - ->with('ptero_resource_reservations') - ->andReturnSelf(); - DB::shouldReceive('where') - ->with('cart_item_id', $cartItemId) - ->andReturnSelf(); - DB::shouldReceive('where') - ->with('status', 'pending') - ->andReturnSelf(); - DB::shouldReceive('first') - ->andReturn($expected); - - $service = $this->createService(); - $result = $service->getByCartItem($cartItemId); - - $this->assertEquals($expected, $result); - } - - public function test_create_logs_audit_entry(): void - { - $this->mockNodeService->shouldReceive('selectBestNode') - ->once() - ->andReturn(['node_id' => 1, 'name' => 'Node 1']); - - DB::shouldReceive('transaction') - ->once() - ->andReturnUsing(fn ($callback) => $callback()); - - DB::shouldReceive('table') - ->with('ptero_resource_reservations') - ->andReturnSelf(); - DB::shouldReceive('where')->andReturnSelf(); - DB::shouldReceive('lockForUpdate')->andReturnSelf(); - DB::shouldReceive('get')->andReturn(collect([])); - DB::shouldReceive('insertGetId')->andReturn(42); - - $this->mockAuditService->shouldReceive('log') - ->once() - ->with('created', 'reservation', 42, Mockery::type('array')) - ->andReturn(1); - - $service = $this->createService(); - $result = $service->create(1, 1, ['memory' => 4096, 'cpu' => 200, 'disk' => 51200], 10, 5); - - $this->assertEquals(42, $result['id']); - $this->assertSame(0.0, $result['pricing']['total']); - $this->assertSame([], $result['pricing']['breakdown']); - $this->assertSame('stored', $result['pricing']['model']); - } - - public function test_confirm_logs_audit_entry_on_success(): void - { - DB::shouldReceive('table')->with('ptero_resource_reservations')->andReturnSelf(); - DB::shouldReceive('where')->times(4)->andReturnSelf(); - DB::shouldReceive('first')->once()->andReturn((object) ['id' => 42, 'token' => 'test_token']); - DB::shouldReceive('update')->andReturn(1); - - $this->mockAuditService->shouldReceive('log') - ->once() - ->with('reservation_confirmed', 'resource_reservation', 42, Mockery::on(fn ($ctx) => $ctx['token_prefix'] === 'test_tok' && $ctx['service_id'] === 42)) - ->andReturn(1); - - $service = $this->createService(); - $result = $service->confirm('test_token', 42); - - $this->assertTrue($result); - } - - public function test_confirm_skips_audit_on_state_drift(): void - { - DB::shouldReceive('table')->with('ptero_resource_reservations')->andReturnSelf(); - DB::shouldReceive('where')->times(4)->andReturnSelf(); - DB::shouldReceive('first')->once()->andReturn(null); - DB::shouldReceive('update')->andReturn(0); - - $this->mockAuditService->shouldReceive('log')->never(); - - $service = $this->createService(); - $result = $service->confirm('expired_token', 42); - - $this->assertFalse($result); + ]); + $this->assertNotNull( + DB::table('ptero_resource_reservations')->where('id', $reservationId)->value('provisioning_started_at') + ); + + $this->assertNotNull($context['provisioning_lease_id']); + $this->assertTrue( + $this->service()->completeProvisioning( + $service->id, + $context['provisioning_lease_id'] + ) + ); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'confirmed', + ]); + $this->assertNotNull( + DB::table('ptero_resource_reservations')->where('id', $reservationId)->value('consumed_at') + ); } - public function test_extend_logs_audit_entry_on_success(): void + public function test_active_provisioning_lease_rejects_a_second_worker(): void { - DB::shouldReceive('table')->with('ptero_resource_reservations')->andReturnSelf(); - DB::shouldReceive('where')->times(3)->andReturnSelf(); - DB::shouldReceive('first')->once()->andReturn((object) ['id' => 42, 'token' => 'test_token']); - DB::shouldReceive('raw')->once()->andReturn('DATE_ADD_SQL'); - DB::shouldReceive('update')->andReturn(1); + $service = $this->makeService(); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + provisioningStartedAt: now() + ); - $this->mockAuditService->shouldReceive('log') - ->once() - ->with('reservation_extended', 'resource_reservation', 42, Mockery::on(fn ($ctx) => $ctx['additional_minutes'] === 15 - && $ctx['token_prefix'] === substr('test_token', 0, 8) - && array_key_exists('node_id', $ctx) - && $ctx['node_id'] === null)) - ->andReturn(1); + $this->configurationService->shouldNotReceive('assertServiceMatches'); - $service = $this->createService(); - $result = $service->extend('test_token', 15); + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('already being provisioned'); - $this->assertTrue($result); + $this->service()->beginProvisioning($service); } - public function test_cleanup_expired_logs_batch_count(): void + public function test_failed_provisioning_releases_only_the_attempt_lease(): void { - DB::shouldReceive('table')->with('ptero_resource_reservations')->andReturnSelf(); - DB::shouldReceive('where')->times(2)->andReturnSelf(); - DB::shouldReceive('update')->andReturn(5); - - $this->mockAuditService->shouldReceive('log') - ->once() - ->with('reservations_expired_batch', 'resource_reservation', 0, Mockery::on(fn ($ctx) => $ctx['count'] === 5 && isset($ctx['run_at']))) - ->andReturn(1); + $service = $this->makeService(); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + provisioningStartedAt: now(), + provisioningLeaseId: 'active-lease' + ); - $service = $this->createService(); - $result = $service->cleanupExpired(); + $this->service()->failProvisioning( + $service->id, + 'active-lease', + new \RuntimeException('Pterodactyl unavailable') + ); - $this->assertEquals(5, $result); + $reservation = DB::table('ptero_resource_reservations')->where('id', $reservationId)->first(); + $this->assertSame('pending', $reservation->status); + $this->assertNull($reservation->provisioning_started_at); + $this->assertSame('Pterodactyl unavailable', $reservation->last_provisioning_error); } - public function test_cancel_audits_with_source_admin(): void + public function test_stale_worker_cannot_consume_or_clear_a_newer_lease(): void { - $token = 'admin_cancel_token'; - $mockReservation = (object) ['id' => 5, 'token' => $token, 'memory' => 4096, 'cpu' => 200, 'disk' => 51200, 'status' => 'pending']; - - DB::shouldReceive('table')->with('ptero_resource_reservations')->andReturnSelf(); - DB::shouldReceive('where')->with('token', $token)->andReturnSelf(); - DB::shouldReceive('first')->once()->andReturn($mockReservation); - DB::shouldReceive('where')->with('status', 'pending')->andReturnSelf(); - DB::shouldReceive('update')->andReturn(1); + $service = $this->makeService(); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + provisioningStartedAt: now(), + provisioningLeaseId: 'new-lease' + ); - $this->mockAuditService->shouldReceive('log') - ->once() - ->with('reservation_cancelled', 'resource_reservation', 5, Mockery::on(fn ($ctx) => $ctx['token_prefix'] === substr($token, 0, 8))) - ->andReturn(1); + try { + $this->service()->completeProvisioning($service->id, 'old-lease'); + $this->fail('Expected stale provisioning lease rejection.'); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString('no longer owns', $exception->getMessage()); + } - $service = $this->createService(); - $service->cancel($token, 'admin override', 'admin'); + $this->service()->failProvisioning( + $service->id, + 'old-lease', + new \RuntimeException('stale worker failed') + ); - $this->addToAssertionCount(1); + $reservation = DB::table('ptero_resource_reservations')->where('id', $reservationId)->first(); + $this->assertSame('pending', $reservation->status); + $this->assertSame('new-lease', $reservation->provisioning_lease_id); + $this->assertNotNull($reservation->provisioning_started_at); + $this->assertNull($reservation->last_provisioning_error); } - public function test_cancel_audits_with_source_customer(): void - { - $token = 'system_cancel_token'; - $mockReservation = (object) ['id' => 6, 'token' => $token, 'memory' => 4096, 'cpu' => 200, 'disk' => 51200, 'status' => 'pending']; - - DB::shouldReceive('table')->with('ptero_resource_reservations')->andReturnSelf(); - DB::shouldReceive('where')->with('token', $token)->andReturnSelf(); - DB::shouldReceive('first')->once()->andReturn($mockReservation); - DB::shouldReceive('where')->with('status', 'pending')->andReturnSelf(); - DB::shouldReceive('update')->andReturn(1); - - $this->mockAuditService->shouldReceive('log') - ->once() - ->with('reservation_cancelled', 'resource_reservation', 6, Mockery::on(fn ($ctx) => $ctx['token_prefix'] === substr($token, 0, 8))) - ->andReturn(1); - - $service = $this->createService(); - $service->cancel($token, null, 'customer'); - - $this->addToAssertionCount(1); - } - public function test_audit_failure_does_not_break_confirm(): void + public function test_completed_reservation_is_idempotent_for_server_reconciliation(): void { - $token = 'audit_fail_token'; - $mockReservation = (object) ['id' => 77, 'token' => $token]; + $service = $this->makeService(); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'confirmed', + consumedAt: now() + ); - DB::shouldReceive('table')->with('ptero_resource_reservations')->andReturnSelf(); - DB::shouldReceive('where')->andReturnSelf(); - DB::shouldReceive('first')->once()->andReturn($mockReservation); - DB::shouldReceive('update')->once()->andReturn(1); + $context = $this->service()->beginProvisioning($service); - $this->mockAuditService->shouldReceive('log')->once() - ->andThrow(new \RuntimeException('audit db down')); - - $service = $this->createService(); - - $this->assertTrue($service->confirm($token, 42)); + $this->assertTrue($context['already_consumed']); + $this->assertTrue($this->service()->completeProvisioning($service->id)); } - public function test_create_with_idempotency_key_returns_existing_on_duplicate(): void + private function service(): ReservationService { - /** @var User $user */ - $user = User::withoutEvents(fn () => User::factory()->create()); - $service = $this->createService(); - - $this->mockNodeService->shouldReceive('selectBestNode') - ->once() - ->andReturn(['node_id' => 1, 'name' => 'Node 1']); - $this->mockAuditService->shouldReceive('log') - ->once() - ->with('created', 'reservation', Mockery::type('int'), Mockery::type('array')); + $reflection = new \ReflectionClass(ReservationService::class); + $service = $reflection->newInstanceWithoutConstructor(); - $first = $service->create(1, 1, $this->standardResources(), null, $user->id, 'dup-key-123'); - $second = $service->create(1, 1, $this->standardResources(), null, $user->id, 'dup-key-123'); + foreach ([ + 'nodeService' => $this->nodeService, + 'configurationService' => $this->configurationService, + 'ttlMinutes' => 15, + ] as $property => $value) { + $instanceProperty = $reflection->getProperty($property); + $instanceProperty->setAccessible(true); + $instanceProperty->setValue($service, $value); + } - $this->assertSame($first['id'], $second['id']); - $this->assertSame($first['token'], $second['token']); - $this->assertSame(1, ResourceReservation::count()); + return $service; } - public function test_create_with_idempotency_key_creates_new_after_original_cancelled(): void + private function makeService(): Service { - /** @var User $user */ $user = User::withoutEvents(fn () => User::factory()->create()); - $service = $this->createService(); - - $this->mockNodeService->shouldReceive('selectBestNode') - ->twice() - ->andReturn(['node_id' => 1, 'name' => 'Node 1']); - $this->mockAuditService->shouldReceive('log') - ->twice() - ->with('created', 'reservation', Mockery::type('int'), Mockery::type('array')); - - $first = $service->create(1, 1, $this->standardResources(), null, $user->id, 'cancelled-key-123'); - ResourceReservation::query()->findOrFail($first['id'])->update(['status' => 'cancelled']); - - $second = $service->create(1, 1, $this->standardResources(), null, $user->id, 'cancelled-key-123'); - - $this->assertNotSame($first['id'], $second['id']); - $this->assertSame(2, ResourceReservation::count()); - } - - public function test_confirm_writes_audit_row(): void - { - $this->app->instance(AuditLogService::class, new AuditLogService); - $actor = User::withoutEvents(fn () => User::factory()->create()); - $this->actingAs($actor); - - $serviceId = DB::table('services')->insertGetId([ - 'user_id' => $actor->id, - 'status' => 'active', + $id = DB::table('services')->insertGetId([ + 'user_id' => $user->id, + 'status' => 'pending', 'currency_code' => 'USD', 'quantity' => 1, 'price' => '0.00', @@ -565,321 +215,51 @@ public function test_confirm_writes_audit_row(): void 'updated_at' => now(), ]); - $reservation = ResourceReservation::create([ - 'token' => 'confirm_token_12345678', - 'user_id' => null, - 'cart_item_id' => null, - 'node_id' => 11, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'calculated_price' => 0, - 'pricing_breakdown' => [], - 'status' => 'pending', - 'expires_at' => now()->addMinutes(15), - ]); - - $this->assertTrue($this->createService()->confirm($reservation->token, $serviceId)); - - $this->assertDatabaseHas('ptero_audit_logs', [ - 'action' => 'reservation_confirmed', - 'entity_type' => 'resource_reservation', - 'entity_id' => $reservation->id, - ]); - - $log = DB::table('ptero_audit_logs')->where('action', 'reservation_confirmed')->latest('id')->first(); - $newValues = json_decode($log->new_values, true); - - $this->assertSame(substr($reservation->token, 0, 8), $newValues['token_prefix']); - $this->assertSame($serviceId, $newValues['service_id']); - $this->assertSame(11, $newValues['node_id']); + return Service::query()->findOrFail($id); } - public function test_cancel_writes_audit_row(): void - { - $this->app->instance(AuditLogService::class, new AuditLogService); - $actor = User::withoutEvents(fn () => User::factory()->create()); - $this->actingAs($actor); - - $reservation = ResourceReservation::create([ - 'token' => 'cancel_token_12345678', - 'user_id' => null, + private function insertReservation( + ?int $serviceId = null, + ?int $cartId = null, + ?int $userId = null, + string $status = 'pending', + mixed $provisioningStartedAt = null, + ?string $provisioningLeaseId = null, + mixed $consumedAt = null + ): int { + return DB::table('ptero_resource_reservations')->insertGetId([ + 'token' => str_repeat((string) random_int(1, 9), 64), 'cart_item_id' => null, - 'node_id' => 12, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'calculated_price' => 0, - 'pricing_breakdown' => [], - 'status' => 'pending', - 'expires_at' => now()->addMinutes(15), - ]); - - $this->assertTrue($this->createService()->cancel($reservation->token)); - - $this->assertDatabaseHas('ptero_audit_logs', [ - 'action' => 'reservation_cancelled', - 'entity_type' => 'resource_reservation', - 'entity_id' => $reservation->id, - ]); - - $log = DB::table('ptero_audit_logs')->where('action', 'reservation_cancelled')->latest('id')->first(); - $newValues = json_decode($log->new_values, true); - - $this->assertSame(substr($reservation->token, 0, 8), $newValues['token_prefix']); - $this->assertSame(12, $newValues['node_id']); - } - - public function test_cleanup_expired_writes_batch_audit_row_with_count(): void - { - $this->app->instance(AuditLogService::class, new AuditLogService); - $actor = User::withoutEvents(fn () => User::factory()->create()); - $this->actingAs($actor); - - ResourceReservation::create([ - 'token' => 'expired_a_token_1234', - 'user_id' => null, - 'cart_item_id' => null, - 'node_id' => 21, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'calculated_price' => 0, - 'pricing_breakdown' => [], - 'status' => 'pending', - 'expires_at' => now()->subMinute(), - ]); - - ResourceReservation::create([ - 'token' => 'expired_b_token_1234', - 'user_id' => null, - 'cart_item_id' => null, - 'node_id' => 22, - 'location_id' => 1, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 51200, - 'calculated_price' => 0, - 'pricing_breakdown' => [], - 'status' => 'pending', - 'expires_at' => now()->subMinute(), - ]); - - $this->assertSame(2, $this->createService()->cleanupExpired()); - - $this->assertDatabaseHas('ptero_audit_logs', [ - 'action' => 'reservations_expired_batch', - 'entity_type' => 'resource_reservation', - 'entity_id' => 0, - ]); - - $log = DB::table('ptero_audit_logs')->where('action', 'reservations_expired_batch')->latest('id')->first(); - $newValues = json_decode($log->new_values, true); - - $this->assertSame(2, $newValues['count']); - $this->assertArrayHasKey('run_at', $newValues); - } - - public function test_create_without_idempotency_key_always_creates_new(): void - { - /** @var User $user */ - $user = User::withoutEvents(fn () => User::factory()->create()); - $service = $this->createService(); - - $this->mockNodeService->shouldReceive('selectBestNode') - ->twice() - ->andReturn(['node_id' => 1, 'name' => 'Node 1']); - $this->mockAuditService->shouldReceive('log') - ->twice() - ->with('created', 'reservation', Mockery::type('int'), Mockery::type('array')); - - $first = $service->create(1, 1, $this->standardResources(), null, $user->id); - $second = $service->create(1, 1, $this->standardResources(), null, $user->id); - - $this->assertNotSame($first['id'], $second['id']); - $this->assertSame(2, ResourceReservation::count()); - } - - - private function createReservation(int $userId, string $token): ResourceReservation - { - return ResourceReservation::create([ - 'token' => $token, + 'cart_id' => $cartId, + 'server_extension_id' => null, + 'panel_identity' => null, + 'service_id' => $serviceId, 'user_id' => $userId, - 'cart_item_id' => null, - 'node_id' => 1, - 'location_id' => 1, + 'product_id' => null, + 'plan_id' => null, + 'quantity' => 1, + 'currency_code' => 'USD', + 'configuration_fingerprint' => str_repeat('a', 64), + 'configuration_payload' => json_encode([ + 'customer_id' => $userId, + 'cart_id' => $cartId, + ]), + 'pricing_version' => str_repeat('b', 64), + 'formula_version' => ReservationConfigurationService::FORMULA_VERSION, + 'node_id' => 4, + 'location_id' => 2, 'memory' => 4096, 'cpu' => 200, 'disk' => 51200, - 'calculated_price' => 0, - 'pricing_breakdown' => [], - 'status' => 'pending', - 'expires_at' => now()->addMinutes(15), - ]); - } - - // ─── Commit-3: actor-aware authorization (cancel) ────────────────────────── - - public function test_cancel_throws_when_actor_does_not_own_reservation(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - $stranger = User::withoutEvents(fn () => User::factory()->create()); - - $this->createReservation($owner->id, 'tok-cancel-deny'); - - $this->mockAuditService->shouldReceive('log')->never(); - - try { - $this->createService()->cancel('tok-cancel-deny', null, 'customer', $stranger); - $this->fail('Expected AuthorizationException was not thrown.'); - } catch (AuthorizationException) { - $this->addToAssertionCount(1); - } - } - - public function test_cancel_succeeds_when_actor_is_owner(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - - $this->createReservation($owner->id, 'tok-cancel-allow'); - - $this->mockAuditService->shouldReceive('log')->once(); - - $result = $this->createService()->cancel('tok-cancel-allow', null, 'customer', $owner); - - $this->assertTrue($result); - } - - public function test_cancel_succeeds_when_actor_is_null(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - - $this->createReservation($owner->id, 'tok-cancel-null'); - - $this->mockAuditService->shouldReceive('log')->once(); - - $result = $this->createService()->cancel('tok-cancel-null', null, 'system', null); - - $this->assertTrue($result); - } - - // ─── Commit-3: actor-aware authorization (extend) ────────────────────────── - - public function test_extend_throws_when_actor_does_not_own_reservation(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - $stranger = User::withoutEvents(fn () => User::factory()->create()); - - $this->createReservation($owner->id, 'tok-extend-deny'); - - $this->mockAuditService->shouldReceive('log')->never(); - - try { - $this->createService()->extend('tok-extend-deny', 15, $stranger); - $this->fail('Expected AuthorizationException was not thrown.'); - } catch (AuthorizationException) { - $this->addToAssertionCount(1); - } - } - - public function test_extend_succeeds_when_actor_is_owner(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - - $this->createReservation($owner->id, 'tok-extend-allow'); - - $this->mockAuditService->shouldReceive('log')->once(); - - $result = $this->createService()->extend('tok-extend-allow', 15, $owner); - - $this->assertTrue($result); - } - - public function test_extend_succeeds_when_actor_is_null(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - - $this->createReservation($owner->id, 'tok-extend-null'); - - $this->mockAuditService->shouldReceive('log')->once(); - - $result = $this->createService()->extend('tok-extend-null', 15, null); - - $this->assertTrue($result); - } - - // ─── Commit-3: actor-aware authorization (confirm) ───────────────────────── - - public function test_confirm_throws_when_actor_does_not_own_reservation(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - $stranger = User::withoutEvents(fn () => User::factory()->create()); - - $this->createReservation($owner->id, 'tok-confirm-deny'); - - $this->mockAuditService->shouldReceive('log')->never(); - - try { - $this->createService()->confirm('tok-confirm-deny', 42, $stranger); - $this->fail('Expected AuthorizationException was not thrown.'); - } catch (AuthorizationException) { - $this->addToAssertionCount(1); - } - } - - public function test_confirm_succeeds_when_actor_is_owner(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - // Direct DB insert avoids App\Models\Service alias-mock contamination from CartItemDeletedListenerTest. - $serviceId = DB::table('services')->insertGetId([ - 'user_id' => $owner->id, - 'status' => 'active', - 'currency_code' => 'USD', - 'quantity' => 1, - 'price' => '0.00', - 'created_at' => now(), - 'updated_at' => now(), - ]); - - $this->createReservation($owner->id, 'tok-confirm-allow'); - - $this->mockAuditService->shouldReceive('log')->once(); - - $result = $this->createService()->confirm('tok-confirm-allow', $serviceId, $owner); - - $this->assertTrue($result); - } - - public function test_confirm_succeeds_when_actor_is_null(): void - { - $owner = User::withoutEvents(fn () => User::factory()->create()); - $serviceId = DB::table('services')->insertGetId([ - 'user_id' => $owner->id, - 'status' => 'active', - 'currency_code' => 'USD', - 'quantity' => 1, - 'price' => '0.00', - 'created_at' => now(), - 'updated_at' => now(), + 'calculated_price' => 12.50, + 'pricing_breakdown' => json_encode([]), + 'status' => $status, + 'expires_at' => now()->addDay(), + 'provisioning_started_at' => $provisioningStartedAt, + 'provisioning_lease_id' => $provisioningLeaseId, + 'consumed_at' => $consumedAt, + 'created_at' => now(), + 'updated_at' => now(), ]); - - $this->createReservation($owner->id, 'tok-confirm-null'); - - $this->mockAuditService->shouldReceive('log')->once(); - - $result = $this->createService()->confirm('tok-confirm-null', $serviceId, null); - - $this->assertTrue($result); - } - - // ─── Commit-3: admin bypass via ResourceReservationPolicy::before() ───────── - - public function test_policy_before_grants_admin_bypass(): void - { - $this->markTestSkipped('Requires full Filament panel registration'); } } diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index de51ed0..86b062f 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -170,7 +170,8 @@ public function test_get_location_availability_excludes_given_reservation_token( $result = $this->service->getLocationAvailability(1, 'token-a'); $this->assertSame(['memory' => 1024, 'cpu' => 50, 'disk' => 5120], $result['nodes'][0]['reserved']); - $this->assertSame(['memory' => 7168, 'cpu' => 350, 'disk' => 46080], $result['nodes'][0]['available']); + $this->assertSame(['memory' => 7168, 'cpu' => null, 'disk' => 46080], $result['nodes'][0]['available']); + $this->assertFalse($result['nodes'][0]['cpu_capacity_enforced']); } public function test_verify_availability_with_self_exclusion_succeeds_on_edge_fit(): void @@ -541,10 +542,10 @@ public function test_snapshot_with_single_location_single_node(): void $this->assertArrayNotHasKey('error', $snapshot); $this->assertCount(1, $snapshot['locations']); $this->assertSame([1], $snapshot['by_location'][1]['nodes']); - $this->assertSame(['memory' => 8192, 'cpu' => 400, 'disk' => 51200], $snapshot['nodes'][1]['totals']); + $this->assertSame(['memory' => 8192, 'cpu' => null, 'disk' => 51200], $snapshot['nodes'][1]['totals']); $this->assertSame(['memory' => 2048, 'cpu' => 100, 'disk' => 10240], $snapshot['nodes'][1]['allocated']); - $this->assertSame(['memory' => 6144, 'cpu' => 300, 'disk' => 40960], $snapshot['nodes'][1]['available']); - $this->assertSame(['memory' => 8192, 'cpu' => 400, 'disk' => 51200], $snapshot['by_location'][1]['totals']); + $this->assertSame(['memory' => 6144, 'cpu' => null, 'disk' => 40960], $snapshot['nodes'][1]['available']); + $this->assertSame(['memory' => 8192, 'cpu' => null, 'disk' => 51200], $snapshot['by_location'][1]['totals']); $this->assertLessThanOrEqual(4, $calls); } @@ -572,9 +573,9 @@ public function test_snapshot_aggregates_across_locations(): void $this->assertCount(5, $snapshot['nodes']); $this->assertSame([1, 2], $snapshot['by_location'][1]['nodes']); $this->assertSame([3, 4, 5], $snapshot['by_location'][2]['nodes']); - $this->assertSame(['memory' => 16384, 'cpu' => 800, 'disk' => 102400], $snapshot['by_location'][1]['totals']); + $this->assertSame(['memory' => 16384, 'cpu' => null, 'disk' => 102400], $snapshot['by_location'][1]['totals']); $this->assertSame(['memory' => 3072, 'cpu' => 150, 'disk' => 15360], $snapshot['by_location'][1]['allocated']); - $this->assertSame(['memory' => 24576, 'cpu' => 1200, 'disk' => 153600], $snapshot['by_location'][2]['totals']); + $this->assertSame(['memory' => 24576, 'cpu' => null, 'disk' => 153600], $snapshot['by_location'][2]['totals']); $this->assertSame(['memory' => 4096, 'cpu' => 200, 'disk' => 20480], $snapshot['by_location'][2]['allocated']); $this->assertLessThanOrEqual(4, $calls); } diff --git a/tests/Unit/StoreReservationRequestTest.php b/tests/Unit/StoreReservationRequestTest.php deleted file mode 100644 index 79032f8..0000000 --- a/tests/Unit/StoreReservationRequestTest.php +++ /dev/null @@ -1,174 +0,0 @@ -createProductWithSliders($sliders); - /** @var User $user */ - $user = User::withoutEvents(fn () => User::factory()->create()); - $payload['product_id'] = $product->id; - $payload['location_id'] ??= 1; - $payload['cart_item_id'] ??= $this->createCartItemForUser($user, $product->id); - - $request = StoreReservationRequest::createFromBase(Request::create( - '/api/dynamic-pterodactyl/reservation', - 'POST', - $payload, - )); - - $request->setContainer($this->app); - $request->setRedirector($this->app->make(Redirector::class)); - $request->setUserResolver(fn () => $user); - - if ($shouldPass) { - $request->validateResolved(); - $this->addToAssertionCount(1); - - return; - } - - try { - $request->validateResolved(); - $this->fail('Expected validation to fail.'); - } catch (ValidationException $exception) { - $this->assertArrayHasKey($errorField, $exception->errors()); - } - } - - public static function reservationPayloadProvider(): array - { - return [ - 'valid request passes' => [ - 'sliders' => [ - 'memory' => ['min' => 1024, 'max' => 8192, 'step' => 1024, 'unit' => 'MB'], - 'cpu' => ['min' => 100, 'max' => 400, 'step' => 100, 'unit' => '%'], - 'disk' => ['min' => 10240, 'max' => 102400, 'step' => 10240, 'unit' => 'MB'], - ], - 'payload' => ['memory' => 4096, 'cpu' => 200, 'disk' => 51200], - 'shouldPass' => true, - ], - 'out of bounds memory rejected' => [ - 'sliders' => [ - 'memory' => ['min' => 1024, 'max' => 8192, 'step' => 1024, 'unit' => 'MB'], - 'cpu' => ['min' => 100, 'max' => 400, 'step' => 100, 'unit' => '%'], - 'disk' => ['min' => 10240, 'max' => 102400, 'step' => 10240, 'unit' => 'MB'], - ], - 'payload' => ['memory' => 99999, 'cpu' => 200, 'disk' => 51200], - 'shouldPass' => false, - 'errorField' => 'memory', - ], - 'wrong step rejected' => [ - 'sliders' => [ - 'memory' => ['min' => 1024, 'max' => 8192, 'step' => 1024, 'unit' => 'MB'], - 'cpu' => ['min' => 100, 'max' => 400, 'step' => 100, 'unit' => '%'], - 'disk' => ['min' => 10240, 'max' => 102400, 'step' => 10240, 'unit' => 'MB'], - ], - 'payload' => ['memory' => 1536, 'cpu' => 200, 'disk' => 51200], - 'shouldPass' => false, - 'errorField' => 'memory', - ], - 'missing required resource rejected' => [ - 'sliders' => [ - 'memory' => ['min' => 1024, 'max' => 8192, 'step' => 1024, 'unit' => 'MB'], - 'cpu' => ['min' => 100, 'max' => 400, 'step' => 100, 'unit' => '%'], - ], - 'payload' => ['memory' => 4096], - 'shouldPass' => false, - 'errorField' => 'cpu', - ], - 'extra resource rejected' => [ - 'sliders' => [ - 'memory' => ['min' => 1024, 'max' => 8192, 'step' => 1024, 'unit' => 'MB'], - 'cpu' => ['min' => 100, 'max' => 400, 'step' => 100, 'unit' => '%'], - ], - 'payload' => ['memory' => 4096, 'cpu' => 200, 'disk' => 51200], - 'shouldPass' => false, - 'errorField' => 'disk', - ], - 'product without slider config rejected' => [ - 'sliders' => [], - 'payload' => ['memory' => 4096, 'cpu' => 200, 'disk' => 51200], - 'shouldPass' => false, - 'errorField' => 'product_id', - ], - ]; - } - - private function createProductWithSliders(array $sliders): Product - { - /** @var Product $product */ - $product = Product::factory()->create(); - - foreach ($sliders as $resourceType => $slider) { - $optionId = DB::table('config_options')->insertGetId([ - 'name' => ucfirst($resourceType), - 'type' => 'dynamic_slider', - 'sort' => 0, - 'hidden' => false, - 'upgradable' => true, - 'metadata' => json_encode([ - 'resource_type' => $resourceType, - 'min' => $slider['min'], - 'max' => $slider['max'], - 'step' => $slider['step'], - 'default' => $slider['min'], - 'unit' => $slider['unit'], - 'display_unit' => $slider['unit'], - 'display_divisor' => 1, - 'pricing' => ['model' => 'linear', 'rate_per_unit' => 1], - ]), - 'created_at' => now(), - 'updated_at' => now(), - ]); - - DB::table('config_option_products')->insert([ - 'product_id' => $product->id, - 'config_option_id' => $optionId, - ]); - } - - return $product; - } - - private function createCartItemForUser(User $user, int $productId): int - { - $cartId = DB::table('carts')->insertGetId([ - 'ulid' => (string) Str::ulid(), - 'user_id' => $user->id, - 'currency_code' => 'USD', - 'created_at' => now(), - 'updated_at' => now(), - ]); - - return DB::table('cart_items')->insertGetId([ - 'cart_id' => $cartId, - 'product_id' => $productId, - 'quantity' => 1, - 'created_at' => now(), - 'updated_at' => now(), - ]); - } -} From 5690837915dd9b870e62c32ed21700a3b6267e5b Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 01:57:21 +1000 Subject: [PATCH 32/95] ci: run cross-repository extension matrix --- .../cross-repository-integration.yml | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 .github/workflows/cross-repository-integration.yml diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml new file mode 100644 index 0000000..41811fa --- /dev/null +++ b/.github/workflows/cross-repository-integration.yml @@ -0,0 +1,107 @@ +name: Cross-repository integration + +on: + pull_request: + push: + branches: + - dynamic-slider + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: dynamic-pterodactyl-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + extension: + name: PHP ${{ matrix.php }} / MariaDB ${{ matrix.mariadb }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: + - '8.3' + - '8.4' + mariadb: + - '11' + - '12' + + services: + mariadb: + image: mariadb:${{ matrix.mariadb }} + env: + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: paymenter_test + ports: + - 3306:3306 + options: >- + --health-cmd="healthcheck.sh --connect --innodb_initialized" + --health-interval=10s + --health-timeout=5s + --health-retries=3 + + steps: + - name: Check out Dynamic Pterodactyl + uses: actions/checkout@v4 + with: + path: dynamic-pterodactyl + + - name: Check out companion Paymenter + uses: actions/checkout@v4 + with: + repository: ObsidianNetwork/Paymenter-Obsidian-Network + ref: codex/paymenter-1.5.6-remediation + path: paymenter + + - name: Assemble extension checkout + run: | + mkdir -p paymenter/extensions/Others/DynamicPterodactyl + rsync -a \ + --exclude=.git \ + --exclude=.github \ + dynamic-pterodactyl/ \ + paymenter/extensions/Others/DynamicPterodactyl/ + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: bcmath, curl, gd, mbstring, mysql, openssl, pdo, tokenizer, xml, zip + tools: composer:v2 + coverage: none + + - name: Install Paymenter dependencies + working-directory: paymenter + run: composer install --prefer-dist --no-progress --no-suggest + + - name: Prepare test database + working-directory: paymenter + env: + APP_ENV: testing + DB_CONNECTION: mariadb + DB_HOST: 127.0.0.1 + DB_PORT: 3306 + DB_DATABASE: paymenter_test + DB_USERNAME: root + DB_PASSWORD: password + run: | + cp .env.example .env + php artisan key:generate --force + php artisan migrate --force + php artisan migrate \ + --path=extensions/Others/DynamicPterodactyl/database/migrations \ + --force + + - name: Run Dynamic Pterodactyl tests + working-directory: paymenter + env: + APP_ENV: testing + DB_CONNECTION: mariadb + DB_HOST: 127.0.0.1 + DB_PORT: 3306 + DB_DATABASE: paymenter_test + DB_USERNAME: root + DB_PASSWORD: password + run: vendor/bin/phpunit -c extensions/Others/DynamicPterodactyl/phpunit.xml From 3f1b1565238577be7133d3df7c716f3f624f6334 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 02:01:42 +1000 Subject: [PATCH 33/95] ci: isolate integration test services --- .../cross-repository-integration.yml | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml index 41811fa..3678041 100644 --- a/.github/workflows/cross-repository-integration.yml +++ b/.github/workflows/cross-repository-integration.yml @@ -55,15 +55,6 @@ jobs: ref: codex/paymenter-1.5.6-remediation path: paymenter - - name: Assemble extension checkout - run: | - mkdir -p paymenter/extensions/Others/DynamicPterodactyl - rsync -a \ - --exclude=.git \ - --exclude=.github \ - dynamic-pterodactyl/ \ - paymenter/extensions/Others/DynamicPterodactyl/ - - name: Set up PHP uses: shivammathur/setup-php@v2 with: @@ -76,16 +67,29 @@ jobs: working-directory: paymenter run: composer install --prefer-dist --no-progress --no-suggest + - name: Assemble extension checkout + run: | + mkdir -p paymenter/extensions/Others/DynamicPterodactyl + rsync -a \ + --exclude=.git \ + --exclude=.github \ + dynamic-pterodactyl/ \ + paymenter/extensions/Others/DynamicPterodactyl/ + - name: Prepare test database working-directory: paymenter env: APP_ENV: testing + CACHE_STORE: array DB_CONNECTION: mariadb DB_HOST: 127.0.0.1 DB_PORT: 3306 DB_DATABASE: paymenter_test DB_USERNAME: root DB_PASSWORD: password + MAIL_MAILER: array + QUEUE_CONNECTION: sync + SESSION_DRIVER: array run: | cp .env.example .env php artisan key:generate --force From 0ba3e5cbfd5066328d0ef69ba6be48ec42cb4579 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 02:05:41 +1000 Subject: [PATCH 34/95] fix(migrations): preserve active cart uniqueness on MariaDB --- Models/ResourceReservation.php | 1 + Services/ReservationService.php | 1 + ...ckout_identity_to_ptero_resource_reservations.php | 9 +++++++-- tests/Unit/ReservationServiceTest.php | 12 ++++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Models/ResourceReservation.php b/Models/ResourceReservation.php index 6c11fda..9a7a145 100644 --- a/Models/ResourceReservation.php +++ b/Models/ResourceReservation.php @@ -15,6 +15,7 @@ class ResourceReservation extends Model 'token', 'idempotency_key', 'cart_item_id', + 'cart_item_guard_id', 'cart_id', 'server_extension_id', 'panel_identity', diff --git a/Services/ReservationService.php b/Services/ReservationService.php index d656553..646b943 100644 --- a/Services/ReservationService.php +++ b/Services/ReservationService.php @@ -131,6 +131,7 @@ public function reserveForCartItem(CartItem $cartItem): array 'token' => $token, 'idempotency_key' => null, 'cart_item_id' => $cartItem->id, + 'cart_item_guard_id' => $cartItem->id, 'cart_id' => $snapshot['cart_id'], 'server_extension_id' => $snapshot['server_extension_id'], 'panel_identity' => $snapshot['panel_identity'], diff --git a/database/migrations/2026_07_25_000001_add_checkout_identity_to_ptero_resource_reservations.php b/database/migrations/2026_07_25_000001_add_checkout_identity_to_ptero_resource_reservations.php index ec1fd00..e8fb02f 100644 --- a/database/migrations/2026_07_25_000001_add_checkout_identity_to_ptero_resource_reservations.php +++ b/database/migrations/2026_07_25_000001_add_checkout_identity_to_ptero_resource_reservations.php @@ -10,6 +10,10 @@ public function up(): void { Schema::table('ptero_resource_reservations', function (Blueprint $table) { + // MariaDB does not allow a generated column to depend on + // cart_item_id because its foreign key uses ON DELETE SET NULL. + // Keep an immutable non-FK copy solely for the partial-unique guard. + $table->unsignedBigInteger('cart_item_guard_id')->nullable()->after('cart_item_id'); $table->unsignedBigInteger('cart_id')->nullable()->after('cart_item_id'); $table->unsignedBigInteger('server_extension_id')->nullable()->after('cart_id'); $table->string('panel_identity', 64)->nullable()->after('server_extension_id'); @@ -28,8 +32,8 @@ public function up(): void $table->unsignedBigInteger('active_cart_item_id') ->nullable() - ->storedAs("CASE WHEN status = 'pending' THEN cart_item_id ELSE NULL END") - ->after('cart_item_id'); + ->storedAs("CASE WHEN status = 'pending' THEN cart_item_guard_id ELSE NULL END") + ->after('cart_item_guard_id'); }); // Every pre-migration pending row came from one of the two superseded @@ -66,6 +70,7 @@ public function down(): void $table->dropIndex('ptero_reservations_fingerprint_idx'); $table->dropColumn([ 'active_cart_item_id', + 'cart_item_guard_id', 'cart_id', 'server_extension_id', 'panel_identity', diff --git a/tests/Unit/ReservationServiceTest.php b/tests/Unit/ReservationServiceTest.php index 5f6d36f..8574549 100644 --- a/tests/Unit/ReservationServiceTest.php +++ b/tests/Unit/ReservationServiceTest.php @@ -4,6 +4,7 @@ use App\Models\Service; use App\Models\User; +use Illuminate\Database\QueryException; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\DB; use Mockery; @@ -62,6 +63,15 @@ public function test_guest_holds_transfer_with_cart_ownership(): void ); } + public function test_only_one_pending_hold_may_use_a_cart_item_guard(): void + { + $this->insertReservation(cartItemGuardId: 42); + + $this->expectException(QueryException::class); + + $this->insertReservation(cartItemGuardId: 42); + } + public function test_begin_keeps_hold_pending_until_complete_consumes_it(): void { $service = $this->makeService(); @@ -221,6 +231,7 @@ private function makeService(): Service private function insertReservation( ?int $serviceId = null, ?int $cartId = null, + ?int $cartItemGuardId = null, ?int $userId = null, string $status = 'pending', mixed $provisioningStartedAt = null, @@ -230,6 +241,7 @@ private function insertReservation( return DB::table('ptero_resource_reservations')->insertGetId([ 'token' => str_repeat((string) random_int(1, 9), 64), 'cart_item_id' => null, + 'cart_item_guard_id' => $cartItemGuardId, 'cart_id' => $cartId, 'server_extension_id' => null, 'panel_identity' => null, From a45d575b03bfa1a2f27837b64ad88c83c1d428fc Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 02:09:41 +1000 Subject: [PATCH 35/95] test: align extension suite with Paymenter 1.5.6 --- tests/Feature/AdminApiTest.php | 26 +++++++++++++++------- tests/Feature/AvailabilityApiTest.php | 8 +++++-- tests/Feature/PricingPreviewParityTest.php | 8 +++++-- tests/LaravelTestCase.php | 20 +++++++++++++++++ tests/Unit/CartItemDeletedListenerTest.php | 4 ++++ tests/Unit/NodeSelectionServiceTest.php | 2 +- 6 files changed, 55 insertions(+), 13 deletions(-) diff --git a/tests/Feature/AdminApiTest.php b/tests/Feature/AdminApiTest.php index 86bb02c..3e5ad6d 100644 --- a/tests/Feature/AdminApiTest.php +++ b/tests/Feature/AdminApiTest.php @@ -59,6 +59,7 @@ public function test_non_admin_user_gets_403(): void { $user = $this->makeRegularUser(); $response = $this->actingAs($user) + ->withSession($this->loginUser($user)) ->getJson('/api/dynamic-pterodactyl/admin/reservations'); $response->assertStatus(403); @@ -73,6 +74,7 @@ public function test_admin_lists_reservations_paginated(): void $this->makeReservation(); $response = $this->actingAs($admin) + ->withSession($this->loginUser($admin)) ->getJson('/api/dynamic-pterodactyl/admin/reservations'); $response->assertStatus(200); @@ -89,6 +91,7 @@ public function test_admin_filters_by_status(): void $this->makeReservation(['status' => 'cancelled']); $response = $this->actingAs($admin) + ->withSession($this->loginUser($admin)) ->getJson('/api/dynamic-pterodactyl/admin/reservations?status=pending'); $response->assertStatus(200); @@ -103,10 +106,12 @@ public function test_admin_cancels_reservation_with_reason(): void $admin = $this->makeAdminUser(); $reservation = $this->makeReservation(['status' => 'pending']); - $response = $this->actingAs($admin)->postJson( - '/api/dynamic-pterodactyl/admin/reservations/'.$reservation->token.'/cancel', - ['reason' => 'Admin cancelled for testing'] - ); + $response = $this->actingAs($admin) + ->withSession($this->loginUser($admin)) + ->postJson( + '/api/dynamic-pterodactyl/admin/reservations/'.$reservation->token.'/cancel', + ['reason' => 'Admin cancelled for testing'] + ); $response->assertStatus(200); $response->assertJson(['success' => true, 'message' => 'Reservation cancelled']); @@ -121,10 +126,12 @@ public function test_admin_cancel_requires_reason(): void $admin = $this->makeAdminUser(); $reservation = $this->makeReservation(['status' => 'pending']); - $response = $this->actingAs($admin)->postJson( - '/api/dynamic-pterodactyl/admin/reservations/'.$reservation->token.'/cancel', - [] - ); + $response = $this->actingAs($admin) + ->withSession($this->loginUser($admin)) + ->postJson( + '/api/dynamic-pterodactyl/admin/reservations/'.$reservation->token.'/cancel', + [] + ); $response->assertStatus(422); } @@ -155,6 +162,7 @@ public function test_admin_capacity_endpoint_returns_structure(): void ]); $response = $this->actingAs($admin) + ->withSession($this->loginUser($admin)) ->getJson('/api/dynamic-pterodactyl/admin/capacity'); $response->assertStatus(200); @@ -169,6 +177,7 @@ public function test_customer_cannot_read_per_node_availability(): void { $user = $this->makeRegularUser(); $response = $this->actingAs($user) + ->withSession($this->loginUser($user)) ->getJson('/api/dynamic-pterodactyl/admin/availability/1/nodes'); $response->assertStatus(403); @@ -191,6 +200,7 @@ public function test_admin_can_read_per_node_availability(): void ]); $response = $this->actingAs($admin) + ->withSession($this->loginUser($admin)) ->getJson('/api/dynamic-pterodactyl/admin/availability/1/nodes'); $response->assertStatus(200); diff --git a/tests/Feature/AvailabilityApiTest.php b/tests/Feature/AvailabilityApiTest.php index 1e4eb09..d52bcb8 100644 --- a/tests/Feature/AvailabilityApiTest.php +++ b/tests/Feature/AvailabilityApiTest.php @@ -31,7 +31,9 @@ public function test_cpu_is_explicitly_not_enforced_as_capacity(): void 'disk' => 1000, ]); - $response = $this->actingAs($user)->getJson('/api/dynamic-pterodactyl/availability/1'); + $response = $this->actingAs($user) + ->withSession($this->loginUser($user)) + ->getJson('/api/dynamic-pterodactyl/availability/1'); $response->assertOk()->assertJson([ 'success' => true, @@ -61,7 +63,9 @@ public function test_has_capacity_true_when_all_resources_positive(): void 'disk' => 1000, ]); - $response = $this->actingAs($user)->getJson('/api/dynamic-pterodactyl/availability/1'); + $response = $this->actingAs($user) + ->withSession($this->loginUser($user)) + ->getJson('/api/dynamic-pterodactyl/availability/1'); $response->assertOk()->assertJson([ 'success' => true, diff --git a/tests/Feature/PricingPreviewParityTest.php b/tests/Feature/PricingPreviewParityTest.php index a985ade..ed2d24b 100644 --- a/tests/Feature/PricingPreviewParityTest.php +++ b/tests/Feature/PricingPreviewParityTest.php @@ -65,7 +65,9 @@ public function test_pricing_calculate_matches_core_base_plus_slider_deltas(): v 'disk' => 20480, ]; - $response = $this->actingAs($user)->postJson('/api/dynamic-pterodactyl/pricing/calculate', $payload); + $response = $this->actingAs($user) + ->withSession($this->loginUser($user)) + ->postJson('/api/dynamic-pterodactyl/pricing/calculate', $payload); $response->assertOk()->assertJson(['success' => true]); @@ -145,7 +147,9 @@ public function test_pricing_calculate_with_foreign_plan_id_returns_client_error 'disk' => 20480, ]; - $response = $this->actingAs($user)->postJson('/api/dynamic-pterodactyl/pricing/calculate', $payload); + $response = $this->actingAs($user) + ->withSession($this->loginUser($user)) + ->postJson('/api/dynamic-pterodactyl/pricing/calculate', $payload); $response->assertStatus(422); $response->assertJson(['success' => false]); diff --git a/tests/LaravelTestCase.php b/tests/LaravelTestCase.php index 25e5000..d87e535 100644 --- a/tests/LaravelTestCase.php +++ b/tests/LaravelTestCase.php @@ -2,6 +2,8 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests; +use App\Models\User; +use App\Models\UserSession; use Illuminate\Contracts\Console\Kernel; use Illuminate\Foundation\Testing\TestCase as BaseTestCase; @@ -52,6 +54,24 @@ public function createApplication() return $app; } + /** + * Create the persisted session required by Paymenter's web middleware. + * + * @return array{user_session: string} + */ + protected function loginUser(User $user): array + { + $userSession = UserSession::create([ + 'user_id' => $user->id, + 'ip_address' => request()->ip(), + 'user_agent' => substr(request()->userAgent() ?? '', 0, 512), + 'last_activity' => now(), + 'expires_at' => null, + ]); + + return ['user_session' => $userSession->ulid]; + } + /** * Create a mock ConfigOption object for dynamic_slider type */ diff --git a/tests/Unit/CartItemDeletedListenerTest.php b/tests/Unit/CartItemDeletedListenerTest.php index 7679a96..0d5c64a 100644 --- a/tests/Unit/CartItemDeletedListenerTest.php +++ b/tests/Unit/CartItemDeletedListenerTest.php @@ -37,6 +37,8 @@ public function test_cart_item_deletion_cancels_by_relationship_without_a_token( (new CartItemDeletedListener($reservationService)) ->handle(new Deleting($cartItem)); + + $this->addToAssertionCount(1); } public function test_bound_or_missing_hold_needs_no_cancellation_log(): void @@ -54,5 +56,7 @@ public function test_bound_or_missing_hold_needs_no_cancellation_log(): void (new CartItemDeletedListener($reservationService)) ->handle(new Deleting($cartItem)); + + $this->addToAssertionCount(1); } } diff --git a/tests/Unit/NodeSelectionServiceTest.php b/tests/Unit/NodeSelectionServiceTest.php index 03bc558..2963491 100644 --- a/tests/Unit/NodeSelectionServiceTest.php +++ b/tests/Unit/NodeSelectionServiceTest.php @@ -322,7 +322,7 @@ public function test_get_max_available_returns_location_max(): void ]; $this->mockResourceService->shouldReceive('getLocationAvailability') - ->with(1, null) + ->with(1) ->andReturn([ 'location_id' => 1, 'nodes' => [], From 930d2845bf6762b8c461a612ba254c9b2415f04f Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 06:54:48 +1000 Subject: [PATCH 36/95] feat(stock): add authoritative dynamic resource lifecycle --- .../cross-repository-integration.yml | 71 + 01-DATABASE.md | 32 +- 02-SERVICES.md | 39 +- 03-API.md | 19 +- 04-EVENTS.md | 29 +- 06-FRONTEND.md | 21 +- 07-PRICING-MODELS.md | 11 +- 08-ALGORITHMS.md | 50 +- 09-IMPLEMENTATION.md | 44 +- AGENTS.md | 8 +- Admin/Pages/SetupWizard.php | 75 +- Admin/Resources/AlertConfigResource.php | 18 +- .../Resources/NodeCapacityPolicyResource.php | 166 ++ .../Pages/CreateNodeCapacityPolicy.php | 16 + .../Pages/EditNodeCapacityPolicy.php | 24 + .../Pages/ListNodeCapacityPolicies.php | 19 + CHANGELOG.md | 71 +- CLAUDE.md | 294 +-- DECISIONS.md | 106 +- DynamicPterodactyl.php | 60 +- .../InvalidResourceSelectionException.php | 7 + .../InvalidStockConfigurationException.php | 7 + Exceptions/StockUnavailableException.php | 7 + .../Api/Admin/AdminReservationController.php | 2 +- .../Api/AvailabilityController.php | 40 +- Http/Controllers/Api/PricingController.php | 157 -- .../Api/ResourceQuoteController.php | 111 + .../Api/UpgradeQuoteController.php | 58 + Http/Requests/ResourceQuoteRequest.php | 36 + Models/AlertConfig.php | 2 + Models/CapacityScope.php | 30 + Models/NodeCapacityPolicy.php | 240 ++ Models/ReservationAllocation.php | 33 + Models/ResourceReservation.php | 61 + Models/UpgradeReservation.php | 30 + .../PaymentAttentionNotification.php | 35 + .../ProvisioningFailedNotification.php | 64 + README.md | 40 +- Services/AlertService.php | 214 +- Services/AllocationSelectionService.php | 240 ++ Services/ConfigOptionSetupService.php | 591 ++++- .../LegacyReservationReadinessService.php | 43 + Services/NodeSelectionService.php | 95 +- .../ProductResourceConfigurationService.php | 679 ++++++ Services/PterodactylInventoryService.php | 867 +++++++ Services/ReservationConfigurationService.php | 418 +++- Services/ReservationService.php | 1722 +++++++++++++- Services/ResourceCalculationService.php | 1491 +++++++----- Services/ResourceQuoteService.php | 270 +++ Services/SliderConfigReaderService.php | 68 - Services/UpgradeReservationService.php | 1654 +++++++++++++ ...able_fulfillment_to_ptero_reservations.php | 195 ++ ..._000002_create_stock_foundation_tables.php | 42 + ..._07_26_000003_add_cpu_alert_thresholds.php | 63 + ...6_07_26_000005_widen_reservation_price.php | 34 + ...10_encrypt_dynamic_pterodactyl_api_key.php | 40 + ...upgrade_identity_to_ptero_reservations.php | 97 + ...ce_one_checkout_commitment_per_service.php | 151 ++ migration-readiness.php | 671 ++++++ routes/api.php | 16 +- tests/AGENTS.md | 2 +- tests/Feature/AdminApiTest.php | 20 + tests/Feature/AvailabilityApiTest.php | 112 +- .../LegacyReservationReadinessTest.php | 303 +++ tests/Feature/ManagedNodeIsolationTest.php | 143 ++ tests/Feature/PricingPreviewParityTest.php | 158 -- tests/Feature/ResourceQuoteApiTest.php | 315 +++ tests/Feature/SetupWizardValidationTest.php | 40 +- tests/LaravelTestCase.php | 6 + tests/TestCase.php | 6 + tests/Unit/AlertServiceTest.php | 102 + tests/Unit/AllocationSelectionServiceTest.php | 141 ++ tests/Unit/ConfigOptionSetupServiceTest.php | 265 ++- tests/Unit/NodeCapacityPolicyTest.php | 32 + tests/Unit/NodeSelectionServiceTest.php | 144 +- ...roductResourceConfigurationServiceTest.php | 541 +++++ .../Unit/PterodactylInventoryServiceTest.php | 445 ++++ .../ReservationConfigurationServiceTest.php | 124 +- tests/Unit/ReservationServiceTest.php | 2090 ++++++++++++++++- tests/Unit/ResourceCalculationServiceTest.php | 1648 ++++++------- tests/Unit/ResourceQuoteServiceTest.php | 301 +++ tests/Unit/SliderConfigReaderServiceTest.php | 134 -- tests/Unit/UpgradeReservationServiceTest.php | 950 ++++++++ 83 files changed, 16898 insertions(+), 2918 deletions(-) create mode 100644 Admin/Resources/NodeCapacityPolicyResource.php create mode 100644 Admin/Resources/NodeCapacityPolicyResource/Pages/CreateNodeCapacityPolicy.php create mode 100644 Admin/Resources/NodeCapacityPolicyResource/Pages/EditNodeCapacityPolicy.php create mode 100644 Admin/Resources/NodeCapacityPolicyResource/Pages/ListNodeCapacityPolicies.php create mode 100644 Exceptions/InvalidResourceSelectionException.php create mode 100644 Exceptions/InvalidStockConfigurationException.php create mode 100644 Exceptions/StockUnavailableException.php delete mode 100644 Http/Controllers/Api/PricingController.php create mode 100644 Http/Controllers/Api/ResourceQuoteController.php create mode 100644 Http/Controllers/Api/UpgradeQuoteController.php create mode 100644 Http/Requests/ResourceQuoteRequest.php create mode 100644 Models/CapacityScope.php create mode 100644 Models/NodeCapacityPolicy.php create mode 100644 Models/ReservationAllocation.php create mode 100644 Models/UpgradeReservation.php create mode 100644 Notifications/PaymentAttentionNotification.php create mode 100644 Notifications/ProvisioningFailedNotification.php create mode 100644 Services/AllocationSelectionService.php create mode 100644 Services/LegacyReservationReadinessService.php create mode 100644 Services/ProductResourceConfigurationService.php create mode 100644 Services/PterodactylInventoryService.php create mode 100644 Services/ResourceQuoteService.php delete mode 100644 Services/SliderConfigReaderService.php create mode 100644 Services/UpgradeReservationService.php create mode 100644 database/migrations/2026_07_26_000001_add_durable_fulfillment_to_ptero_reservations.php create mode 100644 database/migrations/2026_07_26_000002_create_stock_foundation_tables.php create mode 100644 database/migrations/2026_07_26_000003_add_cpu_alert_thresholds.php create mode 100644 database/migrations/2026_07_26_000005_widen_reservation_price.php create mode 100644 database/migrations/2026_07_26_000010_encrypt_dynamic_pterodactyl_api_key.php create mode 100644 database/migrations/2026_07_26_000020_add_upgrade_identity_to_ptero_reservations.php create mode 100644 database/migrations/2026_07_26_000030_enforce_one_checkout_commitment_per_service.php create mode 100644 migration-readiness.php create mode 100644 tests/Feature/LegacyReservationReadinessTest.php create mode 100644 tests/Feature/ManagedNodeIsolationTest.php delete mode 100644 tests/Feature/PricingPreviewParityTest.php create mode 100644 tests/Feature/ResourceQuoteApiTest.php create mode 100644 tests/Unit/AllocationSelectionServiceTest.php create mode 100644 tests/Unit/NodeCapacityPolicyTest.php create mode 100644 tests/Unit/ProductResourceConfigurationServiceTest.php create mode 100644 tests/Unit/PterodactylInventoryServiceTest.php create mode 100644 tests/Unit/ResourceQuoteServiceTest.php delete mode 100644 tests/Unit/SliderConfigReaderServiceTest.php create mode 100644 tests/Unit/UpgradeReservationServiceTest.php diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml index 3678041..71bc1a8 100644 --- a/.github/workflows/cross-repository-integration.yml +++ b/.github/workflows/cross-repository-integration.yml @@ -15,6 +15,77 @@ concurrency: cancel-in-progress: true jobs: + extension-sqlite: + name: PHP ${{ matrix.php }} / SQLite + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: + - '8.3' + - '8.4' + + steps: + - name: Check out Dynamic Pterodactyl + uses: actions/checkout@v4 + with: + path: dynamic-pterodactyl + + - name: Check out companion Paymenter + uses: actions/checkout@v4 + with: + repository: ObsidianNetwork/Paymenter-Obsidian-Network + ref: codex/paymenter-1.5.6-remediation + path: paymenter + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: bcmath, curl, gd, mbstring, mysql, openssl, pdo, pdo_sqlite, sqlite3, tokenizer, xml, zip + tools: composer:v2 + coverage: none + + - name: Install Paymenter dependencies + working-directory: paymenter + run: composer install --prefer-dist --no-progress --no-suggest + + - name: Assemble extension checkout + run: | + mkdir -p paymenter/extensions/Others/DynamicPterodactyl + rsync -a \ + --exclude=.git \ + --exclude=.github \ + dynamic-pterodactyl/ \ + paymenter/extensions/Others/DynamicPterodactyl/ + + - name: Prepare SQLite test database + working-directory: paymenter + env: + APP_ENV: testing + CACHE_STORE: array + DB_CONNECTION: sqlite + DB_DATABASE: database/paymenter_test.sqlite + MAIL_MAILER: array + QUEUE_CONNECTION: sync + SESSION_DRIVER: array + run: | + cp .env.example .env + touch database/paymenter_test.sqlite + php artisan key:generate --force + php artisan migrate --force + php artisan migrate \ + --path=extensions/Others/DynamicPterodactyl/database/migrations \ + --force + + - name: Run Dynamic Pterodactyl tests on SQLite + working-directory: paymenter + env: + APP_ENV: testing + DB_CONNECTION: sqlite + DB_DATABASE: database/paymenter_test.sqlite + run: vendor/bin/phpunit -c extensions/Others/DynamicPterodactyl/phpunit.xml + extension: name: PHP ${{ matrix.php }} / MariaDB ${{ matrix.mariadb }} runs-on: ubuntu-latest diff --git a/01-DATABASE.md b/01-DATABASE.md index bbe7c73..2aad76b 100644 --- a/01-DATABASE.md +++ b/01-DATABASE.md @@ -1,13 +1,16 @@ # Database Schema -The extension owns four live tables: +The extension owns seven live tables: | Table | Purpose | |---|---| | `ptero_resource_reservations` | Authoritative cart-to-provisioning capacity holds | +| `ptero_reservation_allocations` | Exact primary and additional Pterodactyl allocation claims | +| `ptero_node_capacity_policies` | Authoritative physical CPU and overcommit policy per panel/node | +| `ptero_capacity_scopes` | Database rows used to serialize stock and policy mutations per panel/location | | `ptero_audit_logs` | Extension action history | | `ptero_alert_configs` | Per-location alert thresholds | -| `ptero_alert_delivery_logs` | Alert delivery outcomes | +| `ptero_alert_delivery_log` | Alert delivery outcomes | `ptero_pricing_configs` is retired. Paymenter `config_options.metadata` is the pricing source of truth. @@ -26,7 +29,10 @@ The base table is created by `2025_01_01_000001_create_ptero_resource_reservatio | `configuration_payload` | Canonical immutable checkout snapshot, including customer, cart, server extension, hashed panel identity, node, and selected options | | `configuration_fingerprint` | SHA-256 of the canonical payload | | `pricing_version`, `formula_version`, `calculated_price` | Pricing provenance | -| `node_id`, `location_id`, `memory`, `cpu`, `disk` | Reserved placement and limits | +| `node_id`, `location_id`, `memory`, `cpu`, `disk` | Reserved placement and authoritative limits | +| `purpose`, `service_upgrade_id`, `reserved_*` | Checkout or fixed-node upgrade identity and the positive upgrade delta | +| `guaranteed_until`, `paid_committed_at` | Seven-day invoice deadline and non-expiring post-payment commitment | +| `external_server_*`, `external_user_id`, `nest_id`, `egg_id` | Durable Pterodactyl lifecycle identity | The opaque `token` remains for internal/admin lookup of legacy rows. It is not a customer bearer credential and is never placed in browser, URL, cart, or service state. @@ -35,22 +41,32 @@ The opaque `token` remains for internal/admin lookup of legacy rows. It is not a ```mermaid stateDiagram-v2 [*] --> pending: cart create or edit - pending --> pending: login, checkout bind, provisioning lease - pending --> confirmed: Pterodactyl create succeeds + pending --> pending: login or seven-day checkout bind + pending --> paid_committed: invoice payment + paid_committed --> confirmed: exact Pterodactyl state verified pending --> expired: hold deadline passes pending --> cancelled: cart removal or replacement + confirmed --> cancelled: external absence verified ``` -`provisioning_started_at` and the unguessable `provisioning_lease_id` prevent concurrent or stale create workers from consuming the same hold. `consumed_at` records successful Pterodactyl creation. A failed attempt clears only its matching lease and records `last_provisioning_error`; the capacity remains pending until retry or expiry. +`provisioning_started_at` and the unguessable `provisioning_lease_id` +prevent concurrent or stale workers from consuming the same commitment. +`consumed_at` records verified Pterodactyl creation or upgrade. A failed +attempt clears only its matching lease and records +`last_provisioning_error`; paid capacity remains committed for retry and +operator reconciliation. -`active_cart_item_id` is a generated column that is non-null only for pending rows and has a unique index. This enforces one active hold per cart item. +Database-specific generated columns or partial indexes enforce one live +checkout hold per cart item, one live checkout commitment per service, and one +live upgrade commitment per service upgrade. During migration, legacy pending rows without a configuration fingerprint are cancelled. They came from the retired browser/listener token flows and cannot be proved safe. Active carts acquire a fresh server-owned hold on edit or checkout. ## Units - Memory and disk: MiB-compatible integer values used by Pterodactyl. -- CPU: percentage limit (`100` = one core of limit), stored for identity and provisioning but not treated as node capacity. +- CPU: Pterodactyl percentage (`100` = one logical core). Effective node stock + is `physical percentage × overcommit basis points / 10,000`. - Money: decimal snapshot in the cart currency. ## Rollback diff --git a/02-SERVICES.md b/02-SERVICES.md index d9f9fba..700bebf 100644 --- a/02-SERVICES.md +++ b/02-SERVICES.md @@ -4,10 +4,14 @@ |---|---| | `ReservationConfigurationService` | Build canonical checkout payloads, fingerprints, and service-match proofs | | `ReservationService` | Own the hold from cart creation through provisioning | -| `ResourceCalculationService` | Read live Pterodactyl memory/disk inventory and pending holds | -| `NodeSelectionService` | Select a non-maintenance node that fits authoritative resources | +| `PterodactylInventoryService` | Read paginated Pterodactyl 1.12.3+ node, server, location, and allocation inventory | +| `ResourceCalculationService` | Overlay live RAM/disk/CPU/port inventory with local commitments | +| `NodeSelectionService` | Select one public, non-maintenance node that fits the complete vector | | `ConfigOptionSetupService` | Transactionally create normalized native slider options | -| `SliderConfigReaderService` | Read native slider metadata for price previews | +| `ResourceQuoteService` | Compute customer-safe, complete-vector live bounds | +| `UpgradeReservationService` | Quote, reserve, and fulfill fixed-node resource upgrades | +| `AllocationSelectionService` | Deterministically select the exact primary/additional ports used by quotes and reservations | +| `LegacyReservationReadinessService` | Fail extension migration over unresolved legacy lifecycle identity without inferring values | | `AlertService` | Capacity and shortfall notifications | | `AuditLogService` | Best-effort extension audit writes | @@ -32,7 +36,8 @@ The primary methods are: | `reserveForCartItem()` | Create, reuse, or atomically replace one cart hold | | `transferCartOwnership()` | Move guest holds with the cart during login | | `bindCartItemToService()` | Attach the matching hold and extend it through invoice due time | -| `beginProvisioning()` | Lock, validate, and lease the pending hold | +| `commitPaidService()` | Convert the seven-day invoice guarantee to non-expiring paid capacity | +| `beginProvisioning()` | Lock, validate, and lease the paid commitment | | `completeProvisioning()` | Consume it only after Pterodactyl accepts the server | | `failProvisioning()` | Clear the attempt lease while retaining capacity | | `cancelForCartItem()` | Release an unbound hold before cart-item deletion | @@ -41,23 +46,27 @@ All state-changing paths use transactions and row locks. Customer input never su ## ResourceCalculationService -Memory and disk capacity are computed as: +RAM, disk, and CPU capacity are computed as: -`effective total - existing server allocation - unexpired pending reservations` +`effective total - existing Pterodactyl limits - live local commitments` -Memory and disk honor Pterodactyl overallocation. Reads are uncached and the cluster snapshot path batches node/server data. +Memory and disk honor finite Pterodactyl overallocation. CPU uses an enabled, +panel- and node-bound `NodeCapacityPolicy`; the physical value is expressed in +Pterodactyl percentage and multiplied by its configured overcommit ratio. +Nodes with missing/mismatched CPU policy, unlimited existing server limits, +private/maintenance state, unsafe client allocation headroom, or no feasible +port are excluded. -Pterodactyl does not expose authoritative node CPU capacity. Therefore: - -- `total.cpu` and `available.cpu` are `null`; -- `cpu_capacity_enforced` is `false`; -- CPU allocations/reservations remain visible for reporting; -- CPU never rejects or scores a node; -- the selected CPU value is still fingerprinted and passed as the server limit. +The service also reserves exact allocation IDs. A confirmed commitment remains +in the local overlay until the independently-read Pterodactyl server snapshot +proves the pinned identity and complete target vector, preventing a +read-after-write oversell window. ## NodeSelectionService -Candidates must be outside maintenance mode and fit memory and disk. The score is 60% relative memory headroom and 40% relative disk headroom. CPU is deliberately excluded. +Candidates must fit RAM, CPU, disk, and the requested allocation contract on +one eligible node in the selected location. Remaining relative headroom is +scored 50% RAM, 15% CPU, and 35% disk; node ID is the deterministic tie-breaker. ## Configuration setup diff --git a/03-API.md b/03-API.md index 0f1b000..0ca136f 100644 --- a/03-API.md +++ b/03-API.md @@ -2,18 +2,18 @@ All routes are registered from `routes/api.php`. -## Authenticated customer routes +## Customer quote routes Prefix: `/api/dynamic-pterodactyl` -Middleware: `web`, `auth`, `throttle:30,1` | Method | Route | Response | |---|---|---| -| GET | `/availability/{locationId}` | Aggregate location maxima; no node identity | -| POST | `/pricing/calculate` | Core-owned dynamic-slider price preview | -| GET | `/pricing/config/{productId}` | Native slider configuration | +| POST | `/products/{product}/resource-quote` | Guest-safe, complete-vector checkout bounds; `web`, `throttle:30,1` | +| POST | `/services/{service}/upgrade-quote` | Customer-owned, fixed-node upgrade bounds; `web`, `auth`, `throttle:30,1` | -Availability responses set `max_cpu` and `resource_capacity.cpu` to `null` and expose `cpu_capacity_enforced: false`. `has_capacity` uses memory and disk only. +The quote responses expose no node identity. Each bound is feasible for the +complete RAM/CPU/disk/allocation vector, rather than an independent cluster +maximum that might combine different nodes. ## Admin routes @@ -27,8 +27,13 @@ Middleware: `web`, `auth`, `EnsureUserIsAdmin`, `throttle:30,1` | GET | `/capacity` | Cluster capacity summary | | GET | `/availability/{locationId}/nodes` | Raw per-node details | -## Removed customer reservation API +## Removed customer reservation and legacy preview APIs There is no customer create/get/cancel/extend reservation endpoint. Capacity holds are created synchronously by server-side cart listeners. This removes browser idempotency, bearer tokens, session storage, URL state, and client-selected node ownership from the protocol. +The retired `/availability/{locationId}`, `/pricing/calculate`, and +`/pricing/config/{productId}` routes are also absent. Checkout pricing is owned +by Paymenter core, and live stock is available only through the complete-vector +quote contracts above. + Controllers validate and authorize, then delegate to services. Customer errors must never include raw upstream Pterodactyl bodies or node details. diff --git a/04-EVENTS.md b/04-EVENTS.md index afdbc3c..7f85b66 100644 --- a/04-EVENTS.md +++ b/04-EVENTS.md @@ -11,10 +11,11 @@ sequenceDiagram Cart->>Hold: reserveForCartItem Cart->>Hold: transferCartOwnership on login - Cart->>Hold: bindCartItemToService + Cart->>Hold: bind seven-day invoice guarantee + Pay->>Hold: commit paid capacity Pay->>Ptero: dispatch CreateJob Ptero->>Hold: beginProvisioning - Ptero->>Ptero: create exact node and limits + Ptero->>Ptero: create exact node, limits, and ports Ptero->>Hold: completeProvisioning ``` @@ -46,8 +47,22 @@ Missing extension, missing hold, expired hold, or identity drift aborts and roll ## Payment and provisioning -There is no invoice-paid reservation listener. Paymenter dispatches provisioning before `Invoice\Paid`, so confirmation there would be too late. - -The built-in Pterodactyl `createServer()` calls `beginProvisioning()` directly. The returned context overrides the actual lowercase `node`, `location`, `memory`, `cpu`, and `disk` settings. The row remains pending while the external request runs. - -After a successful server create, `completeProvisioning()` marks it confirmed and records `consumed_at`. Failure clears only the provisioning lease. If the server exists on retry, the provisioner reconciles the row and returns the existing server instead of duplicating it. +Payment processing atomically turns the expiring invoice guarantee into a +non-expiring `paid_committed` reservation and moves the service to +`provisioning`. It then dispatches the retryable create job after commit. + +The built-in Pterodactyl `createServer()` calls `beginProvisioning()` directly. +The returned context overrides the actual lowercase `node`, `location`, +`memory`, `cpu`, and `disk` settings plus the exact primary/additional +allocation IDs. The service remains `provisioning` and the row remains +`paid_committed` while the external request runs. + +After the server and complete allocation set are re-read and match, +`completeProvisioning()` marks the reservation confirmed, records durable +server/user identity and `consumed_at`, then activates the service. Failure +clears only the matching lease. If the server exists on retry, the provisioner +reconciles it instead of duplicating it. + +Cancellation shares the same per-service queue overlap key. Capacity and +product stock are released only after the exact numeric Pterodactyl server ID +is proved absent. diff --git a/06-FRONTEND.md b/06-FRONTEND.md index d6052b7..5793095 100644 --- a/06-FRONTEND.md +++ b/06-FRONTEND.md @@ -2,7 +2,9 @@ Paymenter core owns the native `dynamic_slider` input, price preview, Livewire state, and checkout form. -The slider is a native range input with Alpine state and Livewire entanglement. It supports Page Up/Down, Home/End, an accessible value description, a live price output, and server-side validation of min/max values. +The slider is a native range input with Alpine state and Livewire entanglement. +It supports Page Up/Down, Home/End, an accessible value description, a live +price output, and live complete-vector stock bounds. The browser does not create or store reservations. There is: @@ -12,8 +14,21 @@ The browser does not create or store reservations. There is: - no token in URL state; - no client-selected node. -Capacity is checked synchronously when the configured product is added or edited in the cart. A failure is surfaced through Paymenter's `DisplayException` notification handling and the cart mutation is rolled back. +The companion Paymenter theme calls the guest-safe product quote endpoint on +initial load and after location or resource changes. Requests are debounced, +older responses are aborted and ignored, and checkout remains disabled while +stock is loading or unavailable. Every returned maximum is step-aligned and +conditional on the other selected resources fitting the same eligible node. +For example, a configured 32 GiB maximum becomes 23 GiB when the best feasible +node has 23 GiB left, but remains 32 GiB when at least 32 GiB is feasible. + +The browser is advisory. Cart create/edit repeats strict range, step, +complete-vector, CPU, and allocation validation under database locks. A +failure is surfaced through Paymenter's `DisplayException` handling and the +cart mutation is rolled back. Pricing preview remains client-friendly, but Paymenter core recalculates the authoritative price when building the cart and service. -The extension ships no customer JavaScript bundle. Admin pages use Filament 5 and extension Blade views. +Capacity-aware upgrades use the same component with an authenticated, +customer-owned fixed-node quote. Admin pages use Filament 5 and extension Blade +views. diff --git a/07-PRICING-MODELS.md b/07-PRICING-MODELS.md index c6fdb40..6fe29a8 100644 --- a/07-PRICING-MODELS.md +++ b/07-PRICING-MODELS.md @@ -1,12 +1,14 @@ # Pricing Models -> **Related docs**: [02-SERVICES.md](02-SERVICES.md) (SliderConfigReaderService), [05-ADMIN-UI.md](05-ADMIN-UI.md) (configuration forms) +> **Related docs**: [02-SERVICES.md](02-SERVICES.md) (configuration and quote services), [05-ADMIN-UI.md](05-ADMIN-UI.md) (configuration forms) --- ## Overview -Paymenter core now owns `dynamic_slider` pricing math. This extension only stores slider metadata and previews pricing through the same core methods used by checkout and recalculation flows. +Paymenter core owns `dynamic_slider` pricing math. This extension stores slider +metadata and supplies live stock bounds; it does not expose a separate pricing +preview contract. Three pricing models serve different business needs: @@ -246,7 +248,10 @@ Show what's included vs. what's extra: ## Database Storage -Slider pricing is read from ConfigOption metadata built by `Services/ConfigOptionSetupService` and consumed by Paymenter core pricing methods plus `Services/SliderConfigReaderService` for config reads. It is no longer stored in `ptero_pricing_configs.pricing_config`. +Slider pricing is read from ConfigOption metadata built by +`Services/ConfigOptionSetupService` and consumed directly by Paymenter core. +It is no longer stored in `ptero_pricing_configs.pricing_config`, and the +extension exposes no separate customer pricing-preview API. Paymenter core reads the `model` key from ConfigOption metadata and performs the calculation via `ConfigOption::calculateDynamicPriceDelta()`. The extension only stores and reads configuration — no local `calculateLinear()`, `calculateTiered()`, or `calculateBasePlusAddon()` methods exist in the extension. --- diff --git a/08-ALGORITHMS.md b/08-ALGORITHMS.md index 3f233fd..22941fc 100644 --- a/08-ALGORITHMS.md +++ b/08-ALGORITHMS.md @@ -2,33 +2,55 @@ ## Availability -For memory and disk: +For RAM, CPU, and disk: -`available = effective node total - Pterodactyl server allocations - live pending holds` +`available = effective node total - Pterodactyl server limits - live local commitments` -Effective totals apply Pterodactyl's memory/disk overallocation percentage. Pending means `status = pending` and `expires_at > now()`. +Effective RAM/disk totals apply Pterodactyl's finite overallocation percentage. +Effective CPU is the administrator-declared physical percentage multiplied by +the per-node basis-point overcommit ratio. A missing or stale CPU policy makes +the node ineligible; CPU is never inferred from a fabricated default. -CPU is not hard inventory because the Pterodactyl application API exposes server CPU limits but no authoritative node CPU capacity. CPU remains part of the immutable purchase and provisioned server limit, while availability returns null and `cpu_capacity_enforced = false`. +Live commitments include unexpired `pending` checkout/upgrade holds, +non-expiring `paid_committed` rows, and confirmed expectations until live +Pterodactyl inventory proves the exact external target. Upgrade rows reserve +only each positive resource delta while retaining the full immutable target. + +Unassigned Pterodactyl allocation IDs are filtered by local allocation claims. +Required ports, allowed primary-port ranges, and dedicated-IP grouping are +evaluated by the same deterministic selector during quote and reservation. ## Node selection 1. Fetch live nodes for the chosen location. -2. Subtract unexpired pending holds. -3. Reject maintenance nodes. -4. Reject nodes that cannot fit memory or disk. +2. Overlay live local resource and allocation claims. +3. Reject private, maintenance, unbounded, unmanaged-CPU, unsafe-allocation, + or port-infeasible nodes. +4. Reject nodes that cannot fit the complete RAM/CPU/disk vector. 5. Score remaining relative headroom: - - memory: 60%; - - disk: 40%. -6. Choose the highest score. + - memory: 50%; + - CPU: 15%; + - disk: 35%. +6. Choose the highest score, then the lowest node ID on a tie. When replacing a cart hold, the previous token is excluded from availability calculation and the old row is cancelled in the same transaction. ## Concurrency -`reserveForCartItem()` locks pending rows for the location before selecting and inserting. A generated unique active-cart-item column prevents two live holds for one cart item. +`reserveForCartItem()` locks the panel/location capacity-scope row before +reading inventory, selecting allocations, and inserting. Database-specific +unique guards prevent duplicate live cart, checkout-service, and upgrade rows. -`beginProvisioning()` locks the service-bound reservation. A five-minute `provisioning_started_at` lease rejects a second worker. The hold expiry is extended through the lease so scheduled cleanup cannot release capacity during the Pterodactyl request. +Checkout extends the cart hold to exactly seven days. Payment changes it to +`paid_committed`, which has no capacity expiry. `beginProvisioning()` locks the +service-bound commitment; an unguessable lease rejects concurrent or stale +workers. -The row stays pending until the external create succeeds. This closes the gap where a confirmed row stopped counting before a server existed. After success, Pterodactyl is the allocated-capacity source and the reservation becomes confirmed. +The row stays `paid_committed` until the external create and allocation set are +verified. After confirmation, a local expectation overlay remains until the +separately-read Pterodactyl inventory catches up. -Pterodactyl `external_id = service.id` provides reconciliation on retry: an existing server completes the bound reservation instead of creating another. +Pterodactyl `external_id = service.id` initiates reconciliation on retry, but +is never sufficient proof. Numeric server/user IDs, UUID, identifier, panel, +node, nest, egg, resource limits, owner external ID, and allocation IDs must +all match the immutable commitment. diff --git a/09-IMPLEMENTATION.md b/09-IMPLEMENTATION.md index 2b94936..96c8106 100644 --- a/09-IMPLEMENTATION.md +++ b/09-IMPLEMENTATION.md @@ -5,7 +5,8 @@ - Paymenter 1.5.6, Filament 5, Livewire 4. - Paymenter core owns pricing, cart/order/service persistence, and the built-in Pterodactyl provisioner. - Dynamic Pterodactyl owns capacity reads, node selection, reservation identity, and lifecycle validation. -- Pterodactyl owns actual server allocation after a successful create. +- Pterodactyl Panel and Wings 1.12.3+ own actual server state after a verified + create or build update. ## Required cross-repository changes @@ -17,7 +18,10 @@ The Paymenter companion branch must include: - correct `ServiceConfig.slider_value` serialization; - Pterodactyl `createServer()` begin/complete/fail integration; - exact reserved-node and resource overrides; -- removal of browser reservation JavaScript. +- exact allocation-ID create and lifecycle reconciliation; +- guest-safe complete-vector quote JavaScript that fails checkout closed; +- durable payment, cancellation, retry, and capacity-aware upgrade state + machines. The extension branch must include: @@ -26,7 +30,9 @@ The extension branch must include: - server-owned cart listeners; - provisioning lifecycle methods; - lowercase option creation/backfill; -- non-authoritative CPU semantics. +- per-node authoritative CPU policy and overcommit; +- exact allocation claims and fixed-node upgrade deltas; +- legacy readiness and forward-only migration gates. Deploy the Paymenter 1.5.6 baseline and extension migrations together. Migrating the extension without the companion core leaves no caller for service binding/provisioning consumption. @@ -40,11 +46,16 @@ Deploy the Paymenter 1.5.6 baseline and extension migrations together. Migrating | Guest | cart owner and pending holds transfer atomically | | Checkout | missing, expired, foreign, or mismatched hold rolls back order/service | | Payment delay | hold expiry extends to invoice due time | +| Paid state | payment creates non-expiring capacity and service remains provisioning | | Concurrency | duplicate cart hold and duplicate provisioning worker are rejected | -| Node binding | outbound Pterodactyl request uses the stored node and limits | +| Node binding | outbound request uses stored node, limits, and allocation IDs | | Retry | existing external server consumes a pending row idempotently | | Serialization | slider value reaches lowercase service properties and `getServiceProperties()` | -| CPU | changing CPU never rejects a node solely on fabricated capacity | +| CPU | configured physical capacity, overcommit, live server limits, and holds produce the exact bound | +| Bounds | 32 GiB configured / 23 GiB feasible clamps to 23; 100 GiB feasible keeps 32 | +| Upgrade | fixed-node positive delta, immutable source/target, payment, PATCH, and reconciliation | +| Cancellation | exact external absence precedes capacity and product-stock release | +| Ports | quote, hold, create, retry, and cancellation preserve exact allocation identity | Run the Paymenter PHPUnit suite, the extension PHPUnit suite against a dedicated test database, frontend lint/build, and migration up/down checks. The extension test bootstrap must retain its test-database guard. @@ -52,9 +63,20 @@ Run the Paymenter PHPUnit suite, the extension PHPUnit suite against a dedicated After deployment: -1. Run migrations. -2. Verify legacy pending token-flow rows were cancelled with the migration note. -3. Confirm all configured resource/location option keys are lowercase. -4. Inspect one guest-login checkout through paid provisioning. -5. Verify reservation `node_id` equals the created Pterodactyl server node. -6. Verify confirmed rows have `consumed_at` and no active provisioning lease. +1. Back up both databases and enter Paymenter maintenance mode. +2. Deploy/migrate Paymenter core, then run the extension migration/readiness + command. Do not leave maintenance if schema activation or readiness fails. +3. Restart queue workers and verify the scheduler and failed-job monitoring. +4. Confirm Panel and Wings are 1.12.3 or newer, API credentials have node, + server, user, location, nest/egg, and allocation access, and panel URLs + canonicalize to the same identity. +5. Reconcile every legacy commitment reported by the readiness gate. +6. Configure and enable a CPU policy for each dedicated dynamic-stock node. +7. Confirm all configured resource/location keys are lowercase and quantity is + disabled. +8. Run a real-panel guest checkout canary for 32/23 and 32/100 bounds, payment, + queue retry, exact resources/ports, cancellation, and a paid upgrade. +9. Verify reservation `node_id`, resources, owner, nest/egg, and allocation IDs + exactly equal the Pterodactyl server. +10. Verify confirmed rows have `consumed_at`, no active lease, and that external + panel/automation writes are disabled on managed nodes. diff --git a/AGENTS.md b/AGENTS.md index e5034ff..09695e3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -34,7 +34,7 @@ DynamicPterodactyl/ | Capacity / node choice | `Services/ResourceCalculationService.php`, `Services/NodeSelectionService.php` | `08-ALGORITHMS.md` | | Checkout/provisioning reconciliation | `Services/ReservationService.php`, companion Pterodactyl `createServer()` | `04-EVENTS.md` | | Live API surface | `routes/api.php`, `Http/Controllers/Api/` | `03-API.md` | -| Core slider metadata / price preview | `Services/SliderConfigReaderService.php`, `Http/Controllers/Api/PricingController.php` | core `Plan` and `ConfigOption` methods own math | +| Customer stock quotes | `Services/ResourceQuoteService.php`, `Services/UpgradeReservationService.php`, quote controllers | complete-vector bounds; core `Plan` and `ConfigOption` methods own pricing | | Admin pages and actions | `Admin/AGENTS.md` | `resources/views/admin/` | | Tables / casts / lifecycle values | `Models/`, `database/migrations/` | `DECISIONS.md` before stale schema prose | | Test harness and coverage | `tests/AGENTS.md`, `phpunit.xml` | `tests/bootstrap.php` enforces DB isolation | @@ -52,7 +52,7 @@ Caller counts are CodeGraph static counts; Laravel events, container resolution, | `ReservationConfigurationService` | class | `Services/ReservationConfigurationService.php` | cross-layer | canonical payload and fingerprint authority | | `AlertService` | class | `Services/AlertService.php` | 14 | threshold checks, delivery, shortfall notifications | | `NodeSelectionService` | class | `Services/NodeSelectionService.php` | 11 | best-fit scoring over current capacity | -| `SliderConfigReaderService` | class | `Services/SliderConfigReaderService.php` | 5 | native `dynamic_slider` metadata reader | +| `ResourceQuoteService` | class | `Services/ResourceQuoteService.php` | customer | complete-vector checkout bounds without node disclosure | | `ConfigOptionSetupService` | class | `Services/ConfigOptionSetupService.php` | admin | transactional setup-wizard writes into core options | | `ResourceReservation` | model | `Models/ResourceReservation.php` | cross-layer | shared API, policy, service, listener, admin record | | `routes/api.php` | route entry | `routes/api.php` | runtime | customer, checkout, and admin route groups | @@ -63,8 +63,8 @@ Caller counts are CodeGraph static counts; Laravel events, container resolution, - Reservation lifecycle is `pending -> confirmed | expired | cancelled`; `released` is retired. - One pending hold is keyed by `cart_item_id`; reservation writes use transactions, `lockForUpdate()`, and deadlock retry. - Tokens are internal/admin-only and never appear in browser, cart, service, URL, or audit state. -- Controllers validate/authorize then delegate. Customer responses expose aggregate capacity; raw node data is admin-only. -- Route budgets are explicit: availability/pricing/admin `30/min`; there is no customer reservation route. +- Controllers validate/authorize then delegate. Customer responses expose only complete-vector bounds; raw node data is admin-only. +- Quote and admin route budgets are explicit at `30/min`; there is no customer reservation, independent-max availability, or extension pricing route. - Provisioning must call `beginProvisioning()` and `completeProvisioning()` around the external create request. - CPU is never treated as hard node capacity without an external authoritative inventory. - Treat current code plus `DECISIONS.md` as authoritative. diff --git a/Admin/Pages/SetupWizard.php b/Admin/Pages/SetupWizard.php index 38f1935..f415121 100644 --- a/Admin/Pages/SetupWizard.php +++ b/Admin/Pages/SetupWizard.php @@ -90,7 +90,12 @@ public function form(Schema $schema): Schema ->schema([ Select::make('product_id') ->label('Select Product') - ->options(fn () => Product::pluck('name', 'id')) + ->options(fn () => Product::query() + ->where('hidden', false) + ->whereHas('server', fn ($query) => $query + ->where('extension', 'Pterodactyl') + ->where('enabled', true)) + ->pluck('name', 'id')) ->required() ->searchable() ->live() @@ -126,6 +131,8 @@ public function form(Schema $schema): Schema ->label('Base Price') ->prefix('$') ->numeric() + ->required() + ->minValue(0) ->default(0) ->helperText('Monthly base price before resource costs'), ]), @@ -149,21 +156,29 @@ public function form(Schema $schema): Schema ->label('Min') ->suffix('GB') ->numeric() + ->required() + ->minValue(0) ->default(1), TextInput::make('memory_max') ->label('Max') ->suffix('GB') ->numeric() + ->required() + ->minValue(0) ->default(64), TextInput::make('memory_step') ->label('Step') ->suffix('GB') ->numeric() + ->required() + ->minValue(0.0001) ->default(1), TextInput::make('memory_default') ->label('Default') ->suffix('GB') ->numeric() + ->required() + ->minValue(0) ->default(4), ]), ]), @@ -182,20 +197,28 @@ public function form(Schema $schema): Schema ->label('Min') ->suffix('cores') ->numeric() + ->required() + ->minValue(0) ->default(1), TextInput::make('cpu_max') ->label('Max') ->suffix('cores') ->numeric() + ->required() + ->minValue(0) ->default(8), TextInput::make('cpu_step') ->label('Step') ->numeric() + ->required() + ->minValue(0.0001) ->default(1), TextInput::make('cpu_default') ->label('Default') ->suffix('cores') ->numeric() + ->required() + ->minValue(0) ->default(2), ]), ]), @@ -214,21 +237,29 @@ public function form(Schema $schema): Schema ->label('Min') ->suffix('GB') ->numeric() + ->required() + ->minValue(0) ->default(10), TextInput::make('disk_max') ->label('Max') ->suffix('GB') ->numeric() + ->required() + ->minValue(0) ->default(500), TextInput::make('disk_step') ->label('Step') ->suffix('GB') ->numeric() + ->required() + ->minValue(0.0001) ->default(10), TextInput::make('disk_default') ->label('Default') ->suffix('GB') ->numeric() + ->required() + ->minValue(0) ->default(50), ]), ]), @@ -249,18 +280,24 @@ public function form(Schema $schema): Schema ->prefix('$') ->suffix('/GB/mo') ->numeric() + ->required() + ->minValue(0) ->default(0.50), TextInput::make('cpu_rate') ->label('CPU Rate') ->prefix('$') ->suffix('/core/mo') ->numeric() + ->required() + ->minValue(0) ->default(2.00), TextInput::make('disk_rate') ->label('Disk Rate') ->prefix('$') ->suffix('/GB/mo') ->numeric() + ->required() + ->minValue(0) ->default(0.02), ]), ]), @@ -275,11 +312,13 @@ public function form(Schema $schema): Schema TextInput::make('up_to') ->label('Up to (GB)') ->numeric() + ->minValue(0) ->placeholder('∞ (leave empty for unlimited)'), TextInput::make('rate') ->label('Price per GB') ->prefix('$') ->numeric() + ->minValue(0) ->required(), ]) ->columns(2) @@ -299,11 +338,13 @@ public function form(Schema $schema): Schema TextInput::make('up_to') ->label('Up to (cores)') ->numeric() + ->minValue(0) ->placeholder('∞'), TextInput::make('rate') ->label('Price per core') ->prefix('$') ->numeric() + ->minValue(0) ->required(), ]) ->columns(2) @@ -322,11 +363,13 @@ public function form(Schema $schema): Schema TextInput::make('up_to') ->label('Up to (GB)') ->numeric() + ->minValue(0) ->placeholder('∞'), TextInput::make('rate') ->label('Price per GB') ->prefix('$') ->numeric() + ->minValue(0) ->required(), ]) ->columns(2) @@ -347,16 +390,22 @@ public function form(Schema $schema): Schema ->label('Included Memory') ->suffix('GB') ->numeric() + ->required() + ->minValue(0) ->default(4), TextInput::make('cpu_included') ->label('Included CPU') ->suffix('cores') ->numeric() + ->required() + ->minValue(0) ->default(2), TextInput::make('disk_included') ->label('Included Disk') ->suffix('GB') ->numeric() + ->required() + ->minValue(0) ->default(50), ]), ]), @@ -371,18 +420,24 @@ public function form(Schema $schema): Schema ->prefix('$') ->suffix('/GB/mo') ->numeric() + ->required() + ->minValue(0) ->default(0.75), TextInput::make('cpu_overage') ->label('CPU Overage') ->prefix('$') ->suffix('/core/mo') ->numeric() + ->required() + ->minValue(0) ->default(3.00), TextInput::make('disk_overage') ->label('Disk Overage') ->prefix('$') ->suffix('/GB/mo') ->numeric() + ->required() + ->minValue(0) ->default(0.05), ]), ]), @@ -399,7 +454,7 @@ public function form(Schema $schema): Schema ->label('Allowed Locations') ->multiple() ->options(fn () => $this->getLocationOptions()) - ->helperText('Select locations to create a location selector. Leave empty to skip location config option.'), + ->helperText('Select one or more customer choices, or leave empty only when the product has exactly one valid static Pterodactyl location.'), ]), ]), ])->columnSpanFull(), @@ -447,6 +502,22 @@ public function setupConfigOptions(): void if (! empty($selectedLocationIds)) { $allLocations = app(ResourceCalculationService::class)->getLocations(); $locations = array_filter($allLocations, fn ($loc) => in_array($loc['id'], $selectedLocationIds)); + $resolvedLocationIds = collect($locations) + ->pluck('id') + ->map(fn ($id) => (string) $id) + ->sort() + ->values() + ->all(); + $submittedLocationIds = collect($selectedLocationIds) + ->map(fn ($id) => (string) $id) + ->unique() + ->sort() + ->values() + ->all(); + + if ($resolvedLocationIds !== $submittedLocationIds) { + throw new \InvalidArgumentException('One or more selected locations no longer exist on the configured Pterodactyl panel.'); + } } // Call the service to create config options diff --git a/Admin/Resources/AlertConfigResource.php b/Admin/Resources/AlertConfigResource.php index f1732fe..361eeb4 100644 --- a/Admin/Resources/AlertConfigResource.php +++ b/Admin/Resources/AlertConfigResource.php @@ -70,6 +70,20 @@ public static function form(Schema $schema): Schema ->default(95) ->minValue(1) ->maxValue(100), + TextInput::make('cpu_warning_threshold') + ->label('CPU Warning') + ->suffix('%') + ->numeric() + ->default(80) + ->minValue(1) + ->maxValue(100), + TextInput::make('cpu_critical_threshold') + ->label('CPU Critical') + ->suffix('%') + ->numeric() + ->default(95) + ->minValue(1) + ->maxValue(100), TextInput::make('disk_warning_threshold') ->label('Disk Warning') ->suffix('%') @@ -133,9 +147,11 @@ public static function table(Table $table): Table TextColumn::make('thresholds') ->label('Thresholds') ->getStateUsing(fn ($record) => sprintf( - 'Mem: %d%%/%d%% | Disk: %d%%/%d%%', + 'Mem: %d%%/%d%% | CPU: %d%%/%d%% | Disk: %d%%/%d%%', $record->memory_warning_threshold, $record->memory_critical_threshold, + $record->cpu_warning_threshold, + $record->cpu_critical_threshold, $record->disk_warning_threshold, $record->disk_critical_threshold )), diff --git a/Admin/Resources/NodeCapacityPolicyResource.php b/Admin/Resources/NodeCapacityPolicyResource.php new file mode 100644 index 0000000..ce87803 --- /dev/null +++ b/Admin/Resources/NodeCapacityPolicyResource.php @@ -0,0 +1,166 @@ +components([ + Section::make('Authoritative CPU Stock') + ->description( + 'CPU is measured in Pterodactyl percent: 100% equals one logical core. ' + .'Enabling a policy dedicates that node to reservation-backed products; ' + .'Paymenter static provisioning and non-capacity upgrades are blocked there. ' + .'Nodes without an enabled policy are excluded from dynamic stock.' + ) + ->schema([ + Select::make('node_uuid') + ->label('Pterodactyl Node') + ->options(fn (): array => self::nodeOptions()) + ->searchable() + ->required(), + TextInput::make('cpu_capacity_percent') + ->label('Physical CPU Capacity') + ->suffix('%') + ->helperText('For example, an 8-thread node has 800% physical capacity.') + ->numeric() + ->integer() + ->minValue(1) + ->maxValue(NodeCapacityPolicy::MAX_CPU_CAPACITY_PERCENT) + ->required(), + TextInput::make('cpu_overcommit_bps') + ->label('CPU Overcommit Ratio') + ->suffix('basis points') + ->helperText('10,000 = 1.0×, 15,000 = 1.5×, 20,000 = 2.0×.') + ->numeric() + ->integer() + ->default(10000) + ->minValue(1) + ->maxValue(NodeCapacityPolicy::MAX_CPU_OVERCOMMIT_BPS) + ->required(), + Toggle::make('enabled') + ->label('Dedicate this node to dynamic stock') + ->helperText( + 'Enabled nodes must not receive servers or resource changes outside the reservation-backed flow.' + ) + ->default(true), + ]), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + TextColumn::make('node_id')->label('Node ID')->sortable(), + TextColumn::make('node_uuid')->label('Node UUID')->copyable(), + TextColumn::make('cpu_capacity_percent') + ->label('Physical CPU') + ->suffix('%') + ->numeric(), + TextColumn::make('cpu_overcommit_bps') + ->label('Overcommit') + ->formatStateUsing( + fn (int $state): string => number_format($state / 10000, 2).'×' + ), + TextColumn::make('effective_cpu') + ->label('Effective CPU') + ->getStateUsing( + fn (NodeCapacityPolicy $record): string => + number_format($record->effectiveCpuCapacity()).'%' + ), + IconColumn::make('enabled')->boolean(), + ]) + ->recordActions([ + EditAction::make(), + DeleteAction::make(), + ]) + ->toolbarActions([ + DeleteBulkAction::make(), + ]); + } + + public static function getPages(): array + { + return [ + 'index' => ListNodeCapacityPolicies::route('/'), + 'create' => CreateNodeCapacityPolicy::route('/create'), + 'edit' => EditNodeCapacityPolicy::route('/{record}/edit'), + ]; + } + + /** + * Resolve panel and numeric node identity from the live Pterodactyl + * inventory instead of accepting either value from an administrator form. + * + * @param array $data + * @return array + */ + public static function withInventoryIdentity(array $data): array + { + $inventory = app(PterodactylInventoryService::class); + $node = collect($inventory->nodes())->firstWhere( + 'uuid', + (string) ($data['node_uuid'] ?? '') + ); + + if (! is_array($node)) { + throw ValidationException::withMessages([ + 'node_uuid' => 'The selected node is no longer present in Pterodactyl.', + ]); + } + + $data['node_id'] = (int) $node['id']; + $data['location_id'] = (int) $node['location_id']; + $data['panel_identity'] = $inventory->panelIdentity(); + + return $data; + } + + private static function nodeOptions(): array + { + try { + return collect(app(PterodactylInventoryService::class)->nodes()) + ->mapWithKeys(fn (array $node): array => [ + $node['uuid'] => sprintf('%s (#%d)', $node['name'], $node['id']), + ]) + ->all(); + } catch (\Throwable $exception) { + report($exception); + + return []; + } + } +} diff --git a/Admin/Resources/NodeCapacityPolicyResource/Pages/CreateNodeCapacityPolicy.php b/Admin/Resources/NodeCapacityPolicyResource/Pages/CreateNodeCapacityPolicy.php new file mode 100644 index 0000000..b24429e --- /dev/null +++ b/Admin/Resources/NodeCapacityPolicyResource/Pages/CreateNodeCapacityPolicy.php @@ -0,0 +1,16 @@ +>> app(ResourceCalculationService::class)->testConnection() -``` - -## Paymenter Patterns to Follow - -Before implementing, check how the built-in Pterodactyl extension does things: -``` -app/Extensions/Servers/Pterodactyl/ -``` - -Key files to reference: -- `Pterodactyl.php` — main extension class structure -- How it registers routes -- How it uses `ExtensionHelper::getConfig()` - -## When Implementing - -1. Check PROGRESS.md for current state -2. Read relevant doc section -3. Follow existing Paymenter patterns -4. Update PROGRESS.md when done -5. Note any decisions/blockers encountered - -## Common Gotchas - -- Paymenter uses Filament v4, not v3 -- CSRF token required for API POST requests from frontend -- Cart item `properties` is JSON — merge, don't replace -- Pterodactyl API rate limit: 240/min (we use ~10) - ---- - -## Context Compaction Protocol - -**When nearing context limits, BEFORE compacting:** - -1. **Update PROGRESS.md immediately** with: - - Current task and exact stopping point - - Any uncommitted decisions - - What's working, what's broken - - Next specific action to take - -2. **If debugging**, add to PROGRESS.md: - - The error/problem - - What you've tried - - Current hypothesis - -3. **If mid-implementation**, note in PROGRESS.md: - - Files created/modified this session - - What's complete vs. partial - - Any temporary code or TODOs added - -4. **Flush any new decisions** to DECISIONS.md - -5. **Tell the user** you're about to compact so they can save context if needed - -### Quick Checkpoint Template - -Copy this to PROGRESS.md "Current Session State" when checkpointing: - -```markdown -### Checkpoint [timestamp] -**Working on**: [specific task] -**Status**: [working|stuck|almost done] -**Current file**: [path] -**Last completed**: [what] -**Next action**: [specific next step] -**Blockers**: [any issues] -**Notes**: [anything else important] -``` - -## Test Isolation Mandate (dp-13) -Extension phpunit MUST run with `DB_DATABASE=paymenter_test`. The phpunit.xml `` block enforces this; tests/bootstrap.php aborts if violated. See DECISIONS.md for rationale. - - -## CodeRabbit Review Mandate (dp-process-audit, 2026-04-24; v2 2026-04-24) - -Every PR against `dynamic-slider` (and any parent-repo branch) MUST follow `.sisyphus/templates/ralph-loop-contract.md`. This is non-negotiable after the 2026-04-24 incident where two consecutive PRs (#10, #11) merged within minutes of opening, zero CodeRabbit reviews submitted. - -**`.coderabbit.yaml` deployed (v2, 2026-04-24)** - -Both repos now carry a `.coderabbit.yaml` on their default branch: -- `Jordanmuss99/dynamic-pterodactyl` — auto-review on `dp-.*` and `dynamic-slider.*` branches; auto-pause after 10 commits; `request_changes_workflow: true`; `fail_commit_status: true` -- `ObsidianNetwork/Paymenter-Obsidian-Network` — auto-review on `dynamic-slider.*`; same settings - -CodeRabbit reviews automatically on push. No manual `@coderabbitai review` mention needed unless review is absent after ~2 minutes. - -**Required pre-PR local gate**: before `gh pr create`, run: - -```bash -cr review --plain --type committed --base dynamic-slider -``` - -If the working branch is a `dp-*` branch that targets `dynamic-slider`, this local CLI pass is mandatory. - -**Pre-merge gate** (mechanical, run immediately before `gh pr merge`): - -```bash -bash .sisyphus/templates/ralph-loop-verify.sh \ - \ - --repo \ - --expected-base -``` - -Example for extension PR: - -```bash -bash .sisyphus/templates/ralph-loop-verify.sh \ - \ - --repo Jordanmuss99/dynamic-pterodactyl \ - --expected-base '^dynamic-slider$' -``` - -Exit 0 = safe to merge. Non-zero = DO NOT merge. Do not bypass the script. -Use `--allow-actionable --reason "..."`, `--allow-direct-default --reason "..."`, or `--skip-quiet-period --reason "..."` only with explicit driver approval; reasons are audit-logged to `.sisyphus/notepads/ralph-loop-waivers.jsonl`. - -**After APPROVED**: do not rush. Wait the Rule 8 quiet period before merge. Preferred command: - -```bash -bash .sisyphus/templates/ralph-loop-verify.sh \ - \ - --repo Jordanmuss99/dynamic-pterodactyl \ - --expected-base '^dynamic-slider$' \ - --wait -``` - -**Template drift check**: before editing local contract/verifier files, or after syncing from outer Paymenter, run: - -```bash -bash .sisyphus/templates/ralph-loop-verify.sh --check-sync -``` - -**PR author identity** (what CodeRabbit actually checks for entitlement): - -CodeRabbit evaluates the GitHub login on the PR itself (whoever ran `gh pr create` / clicked "Open pull request"). The fork is Pro-entitled under `Jordanmuss99`. The 2026-04-24 incident root cause: PRs #10 and #11 were opened while `gh` was active as `ImStillBlue` (a different account logged in on this host), so CodeRabbit saw them as Free-tier and skipped review. PR #9 opened as `Jordanmuss99` received 3 reviews with the exact same commit authors. - -Before `gh pr create` you MUST: - -```bash -gh auth switch -u Jordanmuss99 -login=$(gh api /user --jq .login) -[ "$login" = "Jordanmuss99" ] || { echo "ABORT: active gh user is $login"; exit 1; } -``` - -PR author on GitHub is immutable. If you open as the wrong user, close the PR and reopen — there is no way to reassign. - -**Commit author email** (secondary — belt-and-braces): - -```bash -git config user.name "Jordanmuss99" -git config user.email "164892154+Jordanmuss99@users.noreply.github.com" -``` - -`164892154+Jordanmuss99@users.noreply.github.com` is the default safe form — it avoids the GH007 push-rejection that blocks `jordanmuss@hotmail.com` (hotmail is marked private on the GitHub account). Use the hotmail address only if the Jordanmuss99 GitHub account's email-privacy setting is changed to allow public email pushes. - -**Orchestrator rule**: when a subagent claims a PR is opened or merged, the driver MUST independently run: - -```bash -gh pr view --repo --json author,createdAt,mergedAt,statusCheckRollup \ - --jq '{author: .author.login, createdAt, mergedAt, cr_status: ([.statusCheckRollup[] | select(.name=="CodeRabbit")] | first | .state)}' -``` - -If `author != "Jordanmuss99"`, OR `mergedAt - createdAt < 3 minutes`, OR `cr_status != "SUCCESS"`, treat as a contract violation. See `.sisyphus/notepads/dp-process-audit/incident-2026-04-24.md` for remediation. - -## Enforceable rules (CodeRabbit reads these) - -- FAIL when: Pterodactyl API responses are cached. Rationale: real-time queries are a settled decision (DECISIONS.md). Rate budget is ~10/min against the 240/min panel limit. -- FAIL when: pricing logic is added to this extension's admin interface or services. Rationale: pricing moved to Paymenter core per DECISIONS.md. The `ptero_pricing_configs` table was dropped in migration `2025_01_01_000005`. -- FAIL when: server provisioning is reimplemented here (createServer, suspendServer, terminateServer). Rationale: companion extension — delegate to `extensions/Servers/Pterodactyl/`. -- FAIL when: changes to this extension are committed from the outer Paymenter repo working tree. Rationale: this directory has its own `.git/`. Use `cd extensions/Others/DynamicPterodactyl && git commit`. +# Dynamic Pterodactyl contributor guide + +Read `README.md`, `DECISIONS.md`, and the nearest `AGENTS.md` before changing +this extension. The July 2026 decisions supersede older browser-reservation, +Filament 4, static-slider, and non-authoritative CPU designs. + +## Current contract + +- Paymenter 1.5.6, Filament 5, Livewire 4, PHP 8.3/8.4. +- Pterodactyl Panel and Wings 1.12.3 or newer. +- Paymenter core owns slider rendering and pricing. +- This extension owns live complete-vector stock, reservations, CPU policy, + allocation claims, and capacity-aware upgrade commitments. +- The built-in Paymenter Pterodactyl extension owns server API mutations. +- Dynamic products fail closed when authoritative stock is unavailable. +- Customer quote responses never expose raw node identity. +- Cart holds last 15 minutes; checkout guarantees capacity for exactly seven + days; successful payment creates a non-expiring `paid_committed` commitment. +- Enabled node-capacity policies dedicate those nodes to the reservation-backed + lifecycle. External panel administrators and automation must not mutate them. +- Quantity is one. Upgrades reserve positive deltas on the existing node. + +## Safety rules + +- Never cache Pterodactyl stock responses. +- Never restore browser reservation tokens or customer reservation endpoints. +- Never calculate independent RAM/CPU/disk maxima; quote the complete resource + vector against one eligible node and its exact free allocations. +- Never infer immutable panel, server, user, node, egg, or allocation identity + for legacy commitments. +- Never mark a capacity-backed invoice paid outside the atomic payment + coordinator. +- Never mark a service active until the external server and allocation set + match its signed commitment. +- Keep Paymenter and this extension's remediation branches deployable together. + +## Required checks + +Run Paymenter's PHP 8.3/8.4 SQLite and MariaDB 11/12 matrix, the extension's +cross-repository matrix, JavaScript stock tests, migration readiness, and a real +Pterodactyl staging canary. Deploy in maintenance mode: core migrations first, +then extension migrations/readiness, restart queue workers, and only then leave +maintenance mode. diff --git a/DECISIONS.md b/DECISIONS.md index 983de88..2eb9ff1 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -18,8 +18,10 @@ Architectural decisions with rationale. Check here before re-debating a settled **Rationale**: - Built-in extension has ~300 lines of server provisioning code - Reimplementing = bugs + missing upstream fixes -- Companion pattern: we handle pricing/sliders, built-in handles server creation -- If our extension fails, graceful degradation (product still works, just no sliders) +- Companion pattern: Paymenter core handles pricing/sliders, this extension + handles stock commitments, and the built-in extension creates the server. +- Dynamic products fail closed if the stock extension is unavailable; a static + fallback would permit overselling. **Trade-off**: Dependent on built-in extension structure. If Paymenter changes it significantly, we need to adapt. @@ -36,7 +38,8 @@ Architectural decisions with rationale. Check here before re-debating a settled - PteroSync (WHMCS module) uses real-time API successfully in production - Caching introduces staleness → overselling risk - Cache invalidation is complex (server created outside our system, admin changes, etc.) -- Pterodactyl allows 240 requests/minute; we use ~5-10 per checkout +- Quote traffic must remain within the deployment's configured Pterodactyl API + rate limit; frontend requests are debounced and superseded reads are aborted - 200ms API call is acceptable for checkout flow **Trade-off**: Slightly slower than cached reads. Acceptable. @@ -104,8 +107,8 @@ Architectural decisions with rationale. Check here before re-debating a settled --- ### Reservation TTL -**Decision**: 15 minutes, extendable to 30 -**Date**: November 2025 +**Decision**: 15-minute cart hold followed by an exact seven-day invoice guarantee +**Date**: November 2025 (revised July 2026) **Status**: Final **Context**: How long to hold resources during checkout? @@ -114,18 +117,20 @@ Architectural decisions with rationale. Check here before re-debating a settled - Too short (5 min): Customer can't complete checkout, frustrating - Too long (1 hour): Resources hoarded, artificial scarcity - 15 minutes: Enough for checkout, not enough to hurt others -- Extension on checkout page: prevents expiry mid-payment +- Checkout atomically converts the cart hold into a seven-day invoice guarantee +- Successful payment converts it into a non-expiring `paid_committed` commitment - Cleanup job runs every minute: resources released promptly -**Trade-off**: Edge case where slow customer loses reservation. Acceptable — they can re-add to cart. +**Trade-off**: Unpaid invoices reserve stock for seven days. This is an explicit +business choice; expired invoices are cancelled and their stock is released. --- ## User Interface ### Filament for Admin -**Decision**: Filament v4 -**Date**: November 2025 +**Decision**: Filament v5 +**Date**: November 2025 (revised July 2026) **Status**: Final **Context**: What framework for admin UI? @@ -217,9 +222,16 @@ Every new hold stores a canonical payload and SHA-256 fingerprint covering custo Checkout binds and extends a pending hold; it does not confirm it. The built-in Pterodactyl provisioner leases the row, overrides the actual node/resource settings, and marks it confirmed only after the external server create succeeds. -### 16. CPU is not hard Pterodactyl inventory +### 16. CPU uses explicit per-node inventory (revised 2026-07-26) -Without an external authoritative inventory, CPU is a fingerprinted/provisioned server limit only. Node eligibility and scoring use memory and disk. Availability explicitly reports `cpu_capacity_enforced = false`. +Pterodactyl does not publish physical node CPU capacity, so the extension owns +an explicit `NodeCapacityPolicy` keyed by normalized panel identity and node +UUID/ID/location. Administrators configure physical capacity in Pterodactyl +percentage (`100` = one logical core) and an overcommit ratio in basis points. +Enabled policies dedicate their nodes to the reservation-backed flow. Live +server CPU limits and local commitments are subtracted from effective policy +capacity; a missing, disabled, or identity-mismatched policy makes the node +ineligible. ### 17. Normalized provisioner keys @@ -270,7 +282,9 @@ Admin-only. Customers never see raw node-level data (node names, FQDNs, maintena ### 5. SetupWizard feature-test shipped status -Unit coverage accepted for dp-06. The full Filament-action lifecycle end-to-end test is deferred to **dp-13** (SetupWizard atomicity + audit-log reliability), since that plan touches `ConfigOptionSetupService` and it's the natural place to wire the E2E test. The skipped placeholder in `tests/Feature/SetupWizardValidationTest.php` carries a `// TODO dp-13:` marker tracking this. +The dp-13 SetupWizard atomicity and audit-reliability work shipped. Current +coverage exercises validation and transactional configuration behavior; the +cross-repository CI gate runs that suite on every remediation PR. ### 6. Test Isolation Mandate (dp-13, Apr 2026) @@ -313,3 +327,71 @@ PR author identity rule (PRIMARY): before `gh pr create`, the orchestrator and a Commit author email (secondary): git config MUST be `user.name = Jordanmuss99` and `user.email = 164892154+Jordanmuss99@users.noreply.github.com` (noreply form — default, avoids the GH007 push rejection that blocks `jordanmuss@hotmail.com`). Use the hotmail address only if the Jordanmuss99 account email-privacy setting is changed to allow public email pushes. Historical dp-11/dp-13/dp-12 commits using the noreply form are grandfathered — those PRs are merged and PR #9 proved the noreply form doesn't break auto-review. Orchestrator verification: when a subagent claims a PR is opened or merged, the orchestrator MUST independently run `gh pr view --json author,createdAt,mergedAt,reviews` and treat `author.login != "Jordanmuss99"` OR `mergedAt - createdAt < 3 minutes` OR `cr_review_count < 1` as a contract violation regardless of the subagent's text. See `.sisyphus/notepads/dp-process-audit/incident-2026-04-24.md` for the remediation protocol. + +## Decisions locked 2026-07-26 + +### 12. One customer stock contract + +The complete-vector resource quote endpoints are the only customer stock +contract: + +- `POST /products/{product}/resource-quote` for checkout; +- `POST /services/{service}/upgrade-quote` for an owned service. + +The older `/availability/{locationId}` endpoint is removed because independent +RAM/CPU/disk maxima can come from different nodes and therefore do not describe +a purchasable configuration. The extension-owned `/pricing/calculate` and +`/pricing/config/{productId}` endpoints are also removed because Paymenter core +owns pricing and slider metadata. Raw node availability remains admin-only. + +This decision supersedes the dp-09 config-reader route and the customer +aggregate-availability portion of decision 4 above. + +### 13. Supported database portability + +The extension follows Paymenter's tested MariaDB and SQLite database support. +MariaDB uses STORED generated columns for partial-unique reservation guards. +SQLite uses equivalent partial unique indexes because SQLite cannot add a +STORED generated column to an existing table. The SQLite migration also +rebuilds the enum-like status CHECK constraint to admit `paid_committed`. +Cross-repository CI must run the extension migrations and suite on PHP 8.3 and +8.4 against both database families. + +### 14. Enabled capacity-policy nodes are dedicated + +An enabled `NodeCapacityPolicy` makes that panel/node exclusive to the +reservation-backed lifecycle. Paymenter's built-in Pterodactyl provisioner +rejects static creates pinned to that node, automatic deployment through any +location containing it, and non-capacity upgrades of servers already on it. +Explicit static paths on unmanaged nodes and locations remain supported. +External panel administrators and automation remain subject to the separate +exclusive-control operational contract. + +### 15. Fixed ports are deterministic across IPs + +Product allocation mappings identify a port, not an IP. If several free IPs on +one node expose the same required port, the lowest allocation ID is selected. +Dedicated-IP requests first constrain candidates to one unused IP group and +then apply the same rule. Quote and reservation placement use the same +`AllocationSelectionService`, so both accept and select the same inventory. +Each non-`NONE` egg environment key maps to exactly one port because +Pterodactyl variables are scalar. Multiple `NONE` entries remain valid +unbound additional allocations. + +### 16. Legacy identity is never inferred + +Extension install, upgrade, and `app:extension:migrate` run a diagnostic +readiness gate after migrations. Confirmed checkout commitments and active +upgrade commitments must contain their complete immutable panel/server/user +identity and signed configuration. The gate reports reservation/service IDs +and missing fields, but never backfills from mutable product settings or a +Pterodactyl external-ID lookup. Web uploads execute the anonymous +`migration-readiness.php` contract directly from the newly activated +destination tree, so a main extension class already loaded from the old version +cannot bypass the new gate. + +Version updates are distinct from deactivation: live confirmed services still +block disable/delete/uninstall, but a same-identity update is allowed in +deployment maintenance after strict migrations/readiness and a queue-worker +restart. Failed updates restore files only; extension migrations are +forward-only and are explicitly never presented as rolled back. diff --git a/DynamicPterodactyl.php b/DynamicPterodactyl.php index b63852f..2c0fa55 100644 --- a/DynamicPterodactyl.php +++ b/DynamicPterodactyl.php @@ -17,11 +17,13 @@ use Paymenter\Extensions\Others\DynamicPterodactyl\Models\ResourceReservation; use Paymenter\Extensions\Others\DynamicPterodactyl\Policies\ResourceReservationPolicy; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AlertService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\LegacyReservationReadinessService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\UpgradeReservationService; #[ExtensionMeta( name: 'Dynamic Pterodactyl', - description: 'Dynamic resource sliders (RAM/CPU/Disk), real-time availability, and 15-min reservations for Pterodactyl products.', + description: 'Dynamic RAM/CPU/disk stock with live quotes, short cart holds, and seven-day invoice guarantees for Pterodactyl products.', version: '4.0.0', author: 'Paymenter', url: '', @@ -59,6 +61,7 @@ public function getConfig($values = []): array 'type' => 'password', 'description' => 'Application API key with read access to Locations, Nodes, and Servers', 'required' => true, + 'encrypted' => true, ], [ 'name' => 'reservation_ttl', @@ -68,6 +71,14 @@ public function getConfig($values = []): array 'default' => 15, 'validation' => 'integer|min:5|max:60', ], + [ + 'name' => 'exclusive_provisioning_control', + 'label' => 'Paymenter exclusively controls eligible nodes', + 'type' => 'checkbox', + 'description' => 'Required for strict stock guarantees. Every node with an enabled CPU policy is dedicated to reservation-backed products: Paymenter blocks its own static creates and non-capacity upgrades, and no administrator, automation, or other billing system may create, move, resize, or assign allocations there.', + 'required' => true, + 'validation' => 'accepted', + ], ]; } @@ -76,15 +87,37 @@ public function getConfig($values = []): array */ public function installed(): void { - ExtensionHelper::runMigrations('extensions/Others/DynamicPterodactyl/database/migrations'); + ExtensionHelper::runMigrationsOrFail('extensions/Others/DynamicPterodactyl/database/migrations'); + $this->assertMigrationReady(); + } + + /** + * Apply every newly shipped extension migration before upgraded code is used. + */ + public function upgraded($oldVersion = null): void + { + ExtensionHelper::runMigrationsOrFail('extensions/Others/DynamicPterodactyl/database/migrations'); + $this->assertMigrationReady(); + } + + /** + * Shared by install/upgrade and Paymenter's explicit extension migration + * command so migrations can never report success over unsafe legacy rows. + */ + public function assertMigrationReady(): void + { + app(LegacyReservationReadinessService::class)->assertReady(); } /** - * Called when extension is uninstalled. + * Durable reservation, payment-attention, allocation, and CPU-policy + * history is deliberately retained on uninstall. Core lifecycle guards + * already require all active work to be drained first; preserving the + * schema keeps completed fulfillment auditable and makes reinstall safe. */ public function uninstalled(): void { - ExtensionHelper::rollbackMigrations('extensions/Others/DynamicPterodactyl/database/migrations'); + // Intentionally no destructive migration rollback. } /** @@ -112,15 +145,28 @@ public function boot(): void // Scheduled cleanup: transition expired pending reservations. // Keeps admin dashboards accurate and preserves the TTL guarantee on confirm(). - Schedule::call(fn () => app(ReservationService::class)->cleanupExpired()) + Schedule::call(function (): void { + app(UpgradeReservationService::class)->expireUnpaidUpgrades(); + app(ReservationService::class)->cleanupExpired(); + }) ->everyMinute() ->name('dynamic-pterodactyl:cleanup-expired-reservations') - ->withoutOverlapping(); + ->withoutOverlapping(5); + + Schedule::call( + function (): void { + app(ReservationService::class)->reconcileStalledPaidCommitments(); + app(UpgradeReservationService::class)->reconcileStalledUpgrades(); + } + ) + ->everyTenMinutes() + ->name('dynamic-pterodactyl:reconcile-paid-commitments') + ->withoutOverlapping(15); Schedule::call(fn () => app(AlertService::class)->checkCapacityAlerts()) ->everyFiveMinutes() ->name('dynamic-pterodactyl:check-capacity-alerts') - ->withoutOverlapping(); + ->withoutOverlapping(10); } /** diff --git a/Exceptions/InvalidResourceSelectionException.php b/Exceptions/InvalidResourceSelectionException.php new file mode 100644 index 0000000..9a6a3e0 --- /dev/null +++ b/Exceptions/InvalidResourceSelectionException.php @@ -0,0 +1,7 @@ +validate([ - 'status' => 'nullable|string|in:pending,confirmed,cancelled,expired', + 'status' => 'nullable|string|in:pending,paid_committed,confirmed,cancelled,expired', 'location_id' => 'nullable|integer', 'node_id' => 'nullable|integer', 'user_id' => 'nullable|integer', diff --git a/Http/Controllers/Api/AvailabilityController.php b/Http/Controllers/Api/AvailabilityController.php index 33cb8e5..c77749d 100644 --- a/Http/Controllers/Api/AvailabilityController.php +++ b/Http/Controllers/Api/AvailabilityController.php @@ -3,54 +3,16 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api; use Illuminate\Http\JsonResponse; -use Paymenter\Extensions\Others\DynamicPterodactyl\Services\NodeSelectionService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceCalculationService; class AvailabilityController { private ResourceCalculationService $resourceService; - private NodeSelectionService $nodeService; public function __construct( - ResourceCalculationService $resourceService, - NodeSelectionService $nodeService + ResourceCalculationService $resourceService ) { $this->resourceService = $resourceService; - $this->nodeService = $nodeService; - } - - public function getByLocation(int $locationId): JsonResponse - { - try { - $locationData = $this->resourceService->getLocationAvailability($locationId); - $maxAvailable = $this->nodeService->getMaxAvailable($locationId, $locationData); - $resourceCapacity = [ - 'memory' => $maxAvailable['memory'] > 0, - 'cpu' => null, - 'disk' => $maxAvailable['disk'] > 0, - ]; - - return response()->json([ - 'success' => true, - 'data' => [ - 'location_id' => $locationId, - 'max_memory' => $maxAvailable['memory'], - 'max_cpu' => $maxAvailable['cpu'], - 'max_disk' => $maxAvailable['disk'], - 'node_count' => count($locationData['nodes']), - 'has_capacity' => $resourceCapacity['memory'] && $resourceCapacity['disk'], - 'resource_capacity' => $resourceCapacity, - 'cpu_capacity_enforced' => false, - ], - ]); - } catch (\Throwable $e) { - \report($e); - - return response()->json([ - 'success' => false, - 'message' => 'Failed to fetch availability', - ], 500); - } } public function getNodes(int $locationId): JsonResponse diff --git a/Http/Controllers/Api/PricingController.php b/Http/Controllers/Api/PricingController.php deleted file mode 100644 index 374c457..0000000 --- a/Http/Controllers/Api/PricingController.php +++ /dev/null @@ -1,157 +0,0 @@ -sliderConfigReader = $sliderConfigReader; - } - - /** - * Calculate price for given resource configuration - */ - public function calculate(Request $request): JsonResponse - { - // Phase 1: validate product_id (static) - $request->validate(['product_id' => 'required|integer|exists:products,id']); - - $product = Product::query()->with(['configOptions', 'plans'])->findOrFail($request->integer('product_id')); - - // Determine which sliders are configured for this product - $sliderOptions = $product->configOptions - ->where('type', 'dynamic_slider') - ->whereNull('parent_id'); - - if ($sliderOptions->isEmpty()) { - return response()->json([ - 'success' => false, - 'message' => 'This product is not configured for dynamic pricing', - ], 404); - } - - // Phase 2: validate plan + only the configured slider fields - $rules = ['plan_id' => 'nullable|integer|exists:plans,id']; - foreach ($sliderOptions as $option) { - $resourceType = $option->getMetadata('resource_type', strtolower($option->name)); - $rules[$resourceType] = 'required|integer|min:1'; - } - - $validated = array_merge( - ['product_id' => $product->id], - $request->validate($rules) - ); - - try { - try { - $plan = $this->resolvePlan($product, $validated['plan_id'] ?? null); - } catch (\InvalidArgumentException $e) { - return response()->json([ - 'success' => false, - 'message' => $e->getMessage(), - ], 422); - } - - $breakdown = []; - $total = 0.0; - $hasSliderInScope = false; - - foreach ($sliderOptions as $option) { - $resourceType = $option->getMetadata('resource_type', strtolower($option->name)); - $value = (float) ($validated[$resourceType] ?? 0); - - if ($value <= 0) { - continue; - } - - $hasSliderInScope = true; - $price = $option->calculateDynamicPriceDelta($value, $plan->billing_period, $plan->billing_unit); - - $breakdown[] = [ - 'resource_type' => $resourceType, - 'label' => $option->name, - 'value' => $value, - 'display_value' => $option->formatValueForDisplay($value), - 'price' => round($price, 2), - 'pricing_model' => $option->getMetadata('pricing.model', 'linear'), - ]; - - $total += $price; - } - - if ($hasSliderInScope) { - $total += $plan->dynamicSliderBasePrice(); - } - - return response()->json([ - 'success' => true, - 'data' => [ - 'total' => round($total, 2), - 'breakdown' => $breakdown, - 'model' => $sliderOptions->first()?->getMetadata('pricing.model', 'linear') ?? 'linear', - ], - ]); - } catch (\Exception $e) { - Log::error('DynamicPterodactyl price calculation failed', [ - 'product_id' => $validated['product_id'], - 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), - ]); - - $payload = [ - 'success' => false, - 'message' => 'Price calculation failed', - ]; - - if (config('app.debug')) { - $payload['error'] = $e->getMessage(); - } - - return response()->json($payload, 500); - } - } - - /** - * Get slider configuration for a product (reads from native ConfigOptions) - */ - public function getConfig(int $productId): JsonResponse - { - $config = $this->sliderConfigReader->getConfig($productId); - - if (! $config['has_config']) { - return response()->json([ - 'success' => false, - 'message' => 'No dynamic slider config options found for this product', - ], 404); - } - - return response()->json([ - 'success' => true, - 'data' => [ - 'product_id' => $productId, - 'sliders' => $config['sliders'], - ], - ]); - } - - private function resolvePlan(Product $product, ?int $planId): Plan - { - if ($planId !== null) { - return $product->plans->firstWhere('id', $planId) - ?? throw new \InvalidArgumentException('Selected plan does not belong to this product'); - } - - return $product->plans->sortBy('sort')->first() - ?? throw new \InvalidArgumentException('No plans found for this product'); - } -} diff --git a/Http/Controllers/Api/ResourceQuoteController.php b/Http/Controllers/Api/ResourceQuoteController.php new file mode 100644 index 0000000..1813cb2 --- /dev/null +++ b/Http/Controllers/Api/ResourceQuoteController.php @@ -0,0 +1,111 @@ +whereKey($product) + ->where('hidden', false) + ->first(); + + if ($productModel === null) { + return response()->json([ + 'message' => 'The requested product is not available.', + ], 404); + } + $productModel->loadMissing([ + 'plans.prices', + 'server', + 'configOptions', + ]); + + if ( + $productModel->stock === 0 + || ! $productModel->price()->available + || $productModel->server?->extension !== 'Pterodactyl' + || ! $productModel->usesDynamicResources() + ) { + return response()->json([ + 'message' => 'The requested product is not available.', + ], 404); + } + + try { + return response()->json([ + 'data' => $this->quotes->quote( + $productModel, + $request->validated('config_options'), + $this->excludedReservationToken( + $productModel, + $request->validated('cart_item_id') + ) + ), + ]); + } catch (InvalidResourceSelectionException $exception) { + return response()->json([ + 'message' => $exception->getMessage(), + ], 422); + } catch (StockUnavailableException $exception) { + return response()->json([ + 'message' => $exception->getMessage(), + ], 409); + } catch (InvalidStockConfigurationException $exception) { + report($exception); + + return response()->json([ + 'message' => 'Dynamic stock is not configured for this product.', + ], 503); + } catch (\Throwable $exception) { + report($exception); + + return response()->json([ + 'message' => 'Dynamic stock is temporarily unavailable.', + ], 503); + } + } + + private function excludedReservationToken( + Product $product, + mixed $cartItemId + ): ?string { + if ($cartItemId === null) { + return null; + } + + $cart = Cart::getOnce(); + $item = $cart->exists + ? $cart->items() + ->whereKey((int) $cartItemId) + ->where('product_id', $product->id) + ->first() + : null; + + if ($item === null) { + throw new InvalidResourceSelectionException( + 'The cart item is not available for this resource quote.' + ); + } + + return ResourceReservation::query() + ->pending() + ->where('cart_item_id', $item->id) + ->value('token'); + } +} diff --git a/Http/Controllers/Api/UpgradeQuoteController.php b/Http/Controllers/Api/UpgradeQuoteController.php new file mode 100644 index 0000000..16216ba --- /dev/null +++ b/Http/Controllers/Api/UpgradeQuoteController.php @@ -0,0 +1,58 @@ +validate([ + 'config_options' => ['required', 'array'], + ]); + + try { + return response()->json([ + 'data' => $this->upgrades->quoteForService( + $service, + $validated['config_options'] + ), + ]); + } catch (\InvalidArgumentException $exception) { + return response()->json([ + 'message' => $exception->getMessage(), + ], 422); + } catch (StockUnavailableException $exception) { + return response()->json([ + 'message' => $exception->getMessage(), + ], 409); + } catch (InvalidStockConfigurationException $exception) { + report($exception); + + return response()->json([ + 'message' => 'Dynamic upgrade stock is not configured safely.', + ], 503); + } catch (\Throwable $exception) { + report($exception); + + return response()->json([ + 'message' => 'Dynamic upgrade stock is temporarily unavailable.', + ], 503); + } + } +} diff --git a/Http/Requests/ResourceQuoteRequest.php b/Http/Requests/ResourceQuoteRequest.php new file mode 100644 index 0000000..d3833a9 --- /dev/null +++ b/Http/Requests/ResourceQuoteRequest.php @@ -0,0 +1,36 @@ + ['required', 'array', 'max:50'], + 'cart_item_id' => [ + 'nullable', + 'integer', + 'min:1', + 'max:'.PHP_INT_MAX, + ], + ]; + } + + protected function failedValidation(Validator $validator): void + { + throw new HttpResponseException(response()->json([ + 'message' => 'The resource quote request is invalid.', + 'errors' => $validator->errors(), + ], 422)); + } +} diff --git a/Models/AlertConfig.php b/Models/AlertConfig.php index ab290e2..59aea44 100644 --- a/Models/AlertConfig.php +++ b/Models/AlertConfig.php @@ -14,6 +14,8 @@ class AlertConfig extends Model 'location_name', 'memory_warning_threshold', 'memory_critical_threshold', + 'cpu_warning_threshold', + 'cpu_critical_threshold', 'disk_warning_threshold', 'disk_critical_threshold', 'email_notifications', diff --git a/Models/CapacityScope.php b/Models/CapacityScope.php new file mode 100644 index 0000000..00e83d5 --- /dev/null +++ b/Models/CapacityScope.php @@ -0,0 +1,30 @@ + 'integer', + ]; + + public function scopeForPanel(Builder $query, string $panelIdentity): Builder + { + return $query->where('panel_identity', $panelIdentity); + } + + public function scopeForLocation(Builder $query, int $locationId): Builder + { + return $query->where('location_id', $locationId); + } +} diff --git a/Models/NodeCapacityPolicy.php b/Models/NodeCapacityPolicy.php new file mode 100644 index 0000000..d112478 --- /dev/null +++ b/Models/NodeCapacityPolicy.php @@ -0,0 +1,240 @@ + 'integer', + 'location_id' => 'integer', + 'cpu_capacity_percent' => 'integer', + 'cpu_overcommit_bps' => 'integer', + 'enabled' => 'boolean', + ]; + + public function scopeForPanel(Builder $query, string $panelIdentity): Builder + { + return $query->where('panel_identity', $panelIdentity); + } + + public function scopeForNode(Builder $query, string $nodeUuid): Builder + { + return $query->where('node_uuid', $nodeUuid); + } + + public function effectiveCpuCapacity(): int + { + if (! $this->enabled) { + return 0; + } + + $capacity = (int) $this->cpu_capacity_percent; + $overcommit = (int) $this->cpu_overcommit_bps; + $this->assertPolicyRange($capacity, $overcommit); + + return intdiv( + $capacity * $overcommit, + 10000 + ); + } + + protected static function booted(): void + { + static::saving(function (self $policy): void { + $policy->assertPolicyRange( + (int) $policy->cpu_capacity_percent, + (int) $policy->cpu_overcommit_bps + ); + }); + } + + public function save(array $options = []) + { + if (! $this->capacityPolicyIsChanging()) { + return parent::save($options); + } + if (DB::transactionLevel() === 0) { + return DB::transaction( + fn () => $this->save($options), + 5 + ); + } + + $this->lockCapacityScopes(); + $this->assertNoLiveCommitment(); + + return parent::save($options); + } + + public function delete() + { + if (! $this->exists) { + return parent::delete(); + } + if (DB::transactionLevel() === 0) { + return DB::transaction( + fn () => $this->delete(), + 5 + ); + } + + $this->lockCapacityScopes(); + $this->assertNoLiveCommitment(); + + return parent::delete(); + } + + private function assertPolicyRange(int $capacity, int $overcommit): void + { + if ($capacity < 1 || $capacity > self::MAX_CPU_CAPACITY_PERCENT) { + throw new \InvalidArgumentException(sprintf( + 'CPU capacity must be between 1 and %d percent.', + self::MAX_CPU_CAPACITY_PERCENT + )); + } + + if ($overcommit < 1 || $overcommit > self::MAX_CPU_OVERCOMMIT_BPS) { + throw new \InvalidArgumentException(sprintf( + 'CPU overcommit must be between 1 and %d basis points.', + self::MAX_CPU_OVERCOMMIT_BPS + )); + } + + if ($capacity > intdiv(PHP_INT_MAX, $overcommit)) { + throw new \InvalidArgumentException( + 'The configured CPU policy exceeds the supported integer range.' + ); + } + } + + private function assertNoLiveCommitment(): bool + { + if (! Schema::hasTable('ptero_resource_reservations')) { + return true; + } + + $scopes = [[ + (string) $this->panel_identity, + (int) $this->node_id, + ]]; + if ($this->exists) { + $scopes[] = [ + (string) $this->getOriginal('panel_identity'), + (int) $this->getOriginal('node_id'), + ]; + } + + foreach (array_unique($scopes, SORT_REGULAR) as [$panel, $node]) { + if (! ResourceReservation::query() + ->holdingCapacity() + ->where('panel_identity', $panel) + ->where('node_id', $node) + ->exists()) { + continue; + } + + throw new \RuntimeException( + 'CPU capacity policy cannot change while this node has a live capacity commitment.' + ); + } + + return true; + } + + private function capacityPolicyIsChanging(): bool + { + return ! $this->exists || $this->isDirty([ + 'panel_identity', + 'node_uuid', + 'node_id', + 'location_id', + 'cpu_capacity_percent', + 'cpu_overcommit_bps', + 'enabled', + ]); + } + + /** + * Serialize the policy write with reservation creation for both the old + * and new location. The lock remains held until the surrounding save or + * delete transaction commits. + */ + private function lockCapacityScopes(): void + { + if (! Schema::hasTable('ptero_resource_reservations')) { + return; + } + if (! Schema::hasTable('ptero_capacity_scopes')) { + throw new \RuntimeException( + 'CPU capacity policy changes require the capacity-scope lock table.' + ); + } + + $scopes = [[ + 'panel_identity' => (string) $this->panel_identity, + 'location_id' => (int) $this->location_id, + ]]; + if ($this->exists) { + $scopes[] = [ + 'panel_identity' => (string) $this->getOriginal( + 'panel_identity' + ), + 'location_id' => (int) $this->getOriginal('location_id'), + ]; + } + $scopes = collect($scopes) + ->unique(fn (array $scope): string => + "{$scope['panel_identity']}:{$scope['location_id']}") + ->sortBy(fn (array $scope): string => + "{$scope['panel_identity']}:" + .str_pad((string) $scope['location_id'], 10, '0', STR_PAD_LEFT)) + ->values(); + + foreach ($scopes as $scope) { + if ( + preg_match( + '/^[a-f0-9]{64}$/D', + $scope['panel_identity'] + ) !== 1 + || $scope['location_id'] <= 0 + ) { + throw new \InvalidArgumentException( + 'A CPU capacity policy requires a valid panel and location identity.' + ); + } + DB::table('ptero_capacity_scopes')->insertOrIgnore([ + ...$scope, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + foreach ($scopes as $scope) { + DB::table('ptero_capacity_scopes') + ->where('panel_identity', $scope['panel_identity']) + ->where('location_id', $scope['location_id']) + ->lockForUpdate() + ->firstOrFail(); + } + } +} diff --git a/Models/ReservationAllocation.php b/Models/ReservationAllocation.php new file mode 100644 index 0000000..20fe927 --- /dev/null +++ b/Models/ReservationAllocation.php @@ -0,0 +1,33 @@ + 'boolean', + 'released_at' => 'datetime', + ]; + + public function reservation(): BelongsTo + { + return $this->belongsTo(ResourceReservation::class, 'reservation_id'); + } +} diff --git a/Models/ResourceReservation.php b/Models/ResourceReservation.php index 9a7a145..6a7ca45 100644 --- a/Models/ResourceReservation.php +++ b/Models/ResourceReservation.php @@ -2,17 +2,30 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Models; +use App\Models\Invoice; use App\Models\Service; use App\Models\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; class ResourceReservation extends Model { + public const STATUS_PENDING = 'pending'; + + public const STATUS_PAID_COMMITTED = 'paid_committed'; + + public const STATUS_CONFIRMED = 'confirmed'; + + public const STATUS_EXPIRED = 'expired'; + + public const STATUS_CANCELLED = 'cancelled'; + protected $table = 'ptero_resource_reservations'; protected $fillable = [ 'token', + 'purpose', 'idempotency_key', 'cart_item_id', 'cart_item_guard_id', @@ -20,6 +33,8 @@ class ResourceReservation extends Model 'server_extension_id', 'panel_identity', 'service_id', + 'service_guard_id', + 'invoice_id', 'user_id', 'product_id', 'plan_id', @@ -39,18 +54,44 @@ class ResourceReservation extends Model 'status', 'admin_notes', 'expires_at', + 'guaranteed_until', + 'paid_committed_at', 'provisioning_started_at', + 'provisioning_attempts', + 'last_provisioning_attempt_at', + 'next_provisioning_attempt_at', 'provisioning_lease_id', 'consumed_at', 'last_provisioning_error', + 'failure_alerted_at', + 'cancellation_requested_at', + 'last_cancellation_error', + 'cancellation_failure_alerted_at', + 'external_server_id', + 'external_user_id', + 'external_server_uuid', + 'external_server_identifier', + 'last_reconciled_at', + 'customer_notified_at', + 'product_stock_released_at', ]; protected $casts = [ 'pricing_breakdown' => 'array', 'configuration_payload' => 'array', 'expires_at' => 'datetime', + 'guaranteed_until' => 'datetime', + 'paid_committed_at' => 'datetime', 'provisioning_started_at' => 'datetime', + 'last_provisioning_attempt_at' => 'datetime', + 'next_provisioning_attempt_at' => 'datetime', 'consumed_at' => 'datetime', + 'failure_alerted_at' => 'datetime', + 'cancellation_requested_at' => 'datetime', + 'cancellation_failure_alerted_at' => 'datetime', + 'last_reconciled_at' => 'datetime', + 'customer_notified_at' => 'datetime', + 'product_stock_released_at' => 'datetime', 'calculated_price' => 'decimal:2', ]; @@ -64,6 +105,16 @@ public function service(): BelongsTo return $this->belongsTo(Service::class); } + public function invoice(): BelongsTo + { + return $this->belongsTo(Invoice::class); + } + + public function allocations(): HasMany + { + return $this->hasMany(ReservationAllocation::class, 'reservation_id'); + } + /** * Scope for pending reservations that haven't expired. */ @@ -73,6 +124,16 @@ public function scopePending($query) ->where('expires_at', '>', now()); } + public function scopeHoldingCapacity($query) + { + return $query->where(function ($query) { + $query->where(function ($query) { + $query->where('status', self::STATUS_PENDING) + ->where('expires_at', '>', now()); + })->orWhere('status', self::STATUS_PAID_COMMITTED); + }); + } + /** * Scope for expired reservations (pending but past TTL). */ diff --git a/Models/UpgradeReservation.php b/Models/UpgradeReservation.php new file mode 100644 index 0000000..c44dca0 --- /dev/null +++ b/Models/UpgradeReservation.php @@ -0,0 +1,30 @@ + 'array', + 'pricing_breakdown' => 'array', + 'expires_at' => 'datetime', + 'guaranteed_until' => 'datetime', + 'paid_committed_at' => 'datetime', + 'provisioning_started_at' => 'datetime', + 'consumed_at' => 'datetime', + 'calculated_price' => 'decimal:2', + ]; + + public function serviceUpgrade(): BelongsTo + { + return $this->belongsTo(ServiceUpgrade::class); + } +} diff --git a/Notifications/PaymentAttentionNotification.php b/Notifications/PaymentAttentionNotification.php new file mode 100644 index 0000000..fbe0d59 --- /dev/null +++ b/Notifications/PaymentAttentionNotification.php @@ -0,0 +1,35 @@ +afterCommit = true; + } + + public function via($notifiable): array + { + return ['mail']; + } + + public function toMail($notifiable): MailMessage + { + return (new MailMessage) + ->subject('[Paymenter] Capacity invoice payment needs refund review') + ->line('Payment activity exists after a dynamic-capacity guarantee expired.') + ->line('Invoice ID: ' . ($this->snapshot['invoice_id'] ?? 'unknown')) + ->line('Service ID: ' . ($this->snapshot['service_id'] ?? 'unknown')) + ->line('Reason: ' . ($this->snapshot['error'] ?? 'unknown')) + ->line('Capacity was not consumed. Review the gateway transaction and issue a refund or account credit.') + ->action('View invoice', url('/admin/invoices/' . ($this->snapshot['invoice_id'] ?? 0) . '/edit')); + } +} diff --git a/Notifications/ProvisioningFailedNotification.php b/Notifications/ProvisioningFailedNotification.php new file mode 100644 index 0000000..02e1b1d --- /dev/null +++ b/Notifications/ProvisioningFailedNotification.php @@ -0,0 +1,64 @@ + $snapshot + */ + public function __construct(public array $snapshot) + { + $this->afterCommit = true; + } + + public function via($notifiable): array + { + return ['mail']; + } + + public function toMail($notifiable): MailMessage + { + $serviceId = (int) ($this->snapshot['service_id'] ?? 0); + $operation = $this->snapshot['operation'] ?? 'provisioning'; + $cancellation = $operation === 'cancellation'; + $upgrade = $operation === 'upgrade'; + + return (new MailMessage) + ->subject(match (true) { + $cancellation => '[Paymenter] Dynamic server cancellation requires attention', + $upgrade => '[Paymenter] Dynamic resource upgrade requires attention', + default => '[Paymenter] Dynamic server provisioning requires attention', + }) + ->line(match (true) { + $cancellation => 'A dynamic server cancellation exhausted its immediate termination retries.', + $upgrade => 'A paid dynamic resource upgrade exhausted its automatic provisioning retries.', + default => 'A paid dynamic-capacity order exhausted its immediate provisioning retries.', + }) + ->when( + $upgrade, + fn (MailMessage $message) => $message->line( + 'Upgrade ID: ' . ($this->snapshot['upgrade_id'] ?? 'unknown') + ) + ) + ->line('Service ID: ' . $serviceId) + ->line('Invoice ID: ' . ($this->snapshot['invoice_id'] ?? 'free service')) + ->line('Reservation ID: ' . ($this->snapshot['reservation_id'] ?? 'unknown')) + ->line('Node ID: ' . ($this->snapshot['node_id'] ?? 'unknown')) + ->line('Attempts: ' . ($this->snapshot['attempts'] ?? 0)) + ->line('Last error: ' . ($this->snapshot['error'] ?? 'unknown')) + ->line(match (true) { + $cancellation => 'The cancellation tombstone remains active. Confirm the external server is deleted before resolving it.', + $upgrade => 'The paid capacity delta remains committed. Reconcile the panel state before manually resolving the upgrade.', + default => 'The paid capacity remains committed and automatic reconciliation will continue.', + }) + ->action('View service', url('/admin/services/' . $serviceId . '/edit')); + } +} diff --git a/README.md b/README.md index cbadf68..58925d8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ # Dynamic Pterodactyl -Companion extension for Paymenter 1.5.6 that adds native RAM/CPU/disk sliders, live memory/disk capacity holds, deterministic node selection, and Filament 5 administration to the built-in Pterodactyl server extension. +Companion extension for Paymenter 1.5.6 that adds native RAM/CPU/disk +sliders, live complete-vector stock, exact port reservations, deterministic +node selection, capacity-aware upgrades, and Filament 5 administration to the +built-in Pterodactyl server extension. + +Production deployments require Pterodactyl Panel and Wings 1.12.3 or newer. +The stock and provisioning API contracts are verified against Panel 1.12.3, +but a real-panel staging canary remains a release gate. ## Ownership @@ -15,10 +22,10 @@ The browser never owns a reservation. A synchronous cart listener creates one se ```mermaid flowchart TD A["Native sliders"] --> B["Transactional cart hold"] - B --> C["Service-bound pending hold"] - C --> D["Reserved node and limits"] - D --> E["Pterodactyl server"] - E --> F["Consumed reservation"] + B --> C["Seven-day invoice guarantee"] + C --> D["Paid commitment"] + D --> E["Exact node, limits, and ports"] + E --> F["Verified Pterodactyl server"] ``` ## Safety properties @@ -27,10 +34,21 @@ flowchart TD - Cart create/edit and checkout fail closed for dynamic products. - Guest ownership transfers with the cart in one transaction. - The immutable fingerprint covers customer, cart, Paymenter server extension, hashed panel identity, product, plan, location, node, resources, quantity, currency, pricing version, and formula version. -- Holds remain pending through payment and external provisioning. -- The actual Pterodactyl request uses the reserved `node`, `memory`, `cpu`, and `disk`. +- A 15-minute cart hold becomes an exact seven-day invoice guarantee at + checkout. Payment converts it to a non-expiring `paid_committed` commitment. +- The actual Pterodactyl request uses the reserved `node`, `memory`, `cpu`, + `disk`, primary allocation, and additional allocations. +- The Paymenter service stays `provisioning` until the external server and its + complete allocation set match the immutable commitment. - Config keys are lowercase and dynamic `ServiceConfig.slider_value` is serialized correctly. -- CPU is a provisioned limit, not fabricated hard node inventory. +- CPU is authoritative stock backed by an explicit per-node physical capacity + and configurable basis-point overcommit policy. Nodes without an enabled + policy are ineligible. +- Enabled capacity-policy nodes are dedicated to the reservation-backed flow; + external administrators and automation must not mutate their stock. +- Dynamic resource upgrades reserve a positive capacity delta on the server's + existing node and reconcile the exact build before local billing state moves. +- Dynamic products force quantity to one. - Customer reservation tokens and reservation endpoints do not exist. ## Documentation @@ -49,6 +67,10 @@ flowchart TD ## Installation boundary -This extension must be deployed with the companion Paymenter remediation branch. Run the Paymenter and extension migrations together, then execute both test suites against a dedicated test database. +This extension must be deployed with the companion Paymenter remediation +branch. Enter maintenance mode, deploy and migrate Paymenter core first, run +the extension migration/readiness gate, restart queue workers, and then leave +maintenance mode. Migrations are forward-only: a failure after schema +activation must remain in maintenance for operator recovery. The extension stores no cached Pterodactyl capacity. Customer responses expose aggregate location signals only; raw node data remains admin-only. diff --git a/Services/AlertService.php b/Services/AlertService.php index 1ba6ced..a05fd87 100644 --- a/Services/AlertService.php +++ b/Services/AlertService.php @@ -13,6 +13,8 @@ use Paymenter\Extensions\Others\DynamicPterodactyl\Models\AlertConfig; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\AlertDeliveryLog; use Paymenter\Extensions\Others\DynamicPterodactyl\Notifications\CapacityAlertNotification; +use Paymenter\Extensions\Others\DynamicPterodactyl\Notifications\PaymentAttentionNotification; +use Paymenter\Extensions\Others\DynamicPterodactyl\Notifications\ProvisioningFailedNotification; use Paymenter\Extensions\Others\DynamicPterodactyl\Notifications\ReservationShortfallNotification; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\Concerns\AuditsExtensionActions; @@ -78,48 +80,50 @@ private function checkThresholds(array $availability, object $config): array { $alerts = []; - $memoryUtilization = $availability['total_capacity']['memory'] > 0 - ? ($availability['total_allocated']['memory'] / $availability['total_capacity']['memory']) * 100 - : 0; - - $diskUtilization = $availability['total_capacity']['disk'] > 0 - ? ($availability['total_allocated']['disk'] / $availability['total_capacity']['disk']) * 100 - : 0; - - if ($memoryUtilization >= $config->memory_critical_threshold) { - $alerts[] = [ - 'type' => 'critical', - 'resource' => 'memory', - 'utilization' => $memoryUtilization, - 'usage_percent' => round($memoryUtilization, 1), - 'threshold' => (int) $config->memory_critical_threshold, - ]; - } elseif ($memoryUtilization >= $config->memory_warning_threshold) { - $alerts[] = [ - 'type' => 'warning', - 'resource' => 'memory', - 'utilization' => $memoryUtilization, - 'usage_percent' => round($memoryUtilization, 1), - 'threshold' => (int) $config->memory_warning_threshold, - ]; - } - - if ($diskUtilization >= $config->disk_critical_threshold) { - $alerts[] = [ - 'type' => 'critical', - 'resource' => 'disk', - 'utilization' => $diskUtilization, - 'usage_percent' => round($diskUtilization, 1), - 'threshold' => (int) $config->disk_critical_threshold, - ]; - } elseif ($diskUtilization >= $config->disk_warning_threshold) { - $alerts[] = [ - 'type' => 'warning', - 'resource' => 'disk', - 'utilization' => $diskUtilization, - 'usage_percent' => round($diskUtilization, 1), - 'threshold' => (int) $config->disk_warning_threshold, - ]; + foreach (['memory', 'cpu', 'disk'] as $resource) { + $capacity = (int) data_get( + $availability, + "total_capacity.{$resource}", + 0 + ); + $available = data_get( + $availability, + "total_available.{$resource}" + ); + $used = $available !== null + ? max(0, $capacity - (int) $available) + : (int) data_get( + $availability, + "total_allocated.{$resource}", + 0 + ); + $utilization = $capacity > 0 + ? ($used / $capacity) * 100 + : 0.0; + $warning = (int) ( + $config->{"{$resource}_warning_threshold"} ?? 80 + ); + $critical = (int) ( + $config->{"{$resource}_critical_threshold"} ?? 95 + ); + + if ($utilization >= $critical) { + $alerts[] = [ + 'type' => 'critical', + 'resource' => $resource, + 'utilization' => $utilization, + 'usage_percent' => round($utilization, 1), + 'threshold' => $critical, + ]; + } elseif ($utilization >= $warning) { + $alerts[] = [ + 'type' => 'warning', + 'resource' => $resource, + 'utilization' => $utilization, + 'usage_percent' => round($utilization, 1), + 'threshold' => $warning, + ]; + } } return $alerts; @@ -360,6 +364,132 @@ public function notifyShortfall( } } + /** + * Notify operators after the immediate queue retry series is exhausted. + * ReservationService persists a deduplication timestamp before calling this. + * + * @param array $snapshot + */ + public function notifyProvisioningFailure(array $snapshot): void + { + $operation = ($snapshot['operation'] ?? 'provisioning') === 'cancellation' + ? 'cancellation' + : 'provisioning'; + $recipients = $this->getAdminRecipients(); + if ($recipients->isEmpty()) { + Log::critical("Dynamic server {$operation} requires attention", $snapshot); + + return; + } + + foreach ($recipients as $recipient) { + try { + $recipient->notify(new ProvisioningFailedNotification($snapshot)); + } catch (\Throwable $exception) { + Log::error("Failed to notify operator about {$operation} failure", [ + 'service_id' => $snapshot['service_id'] ?? null, + 'recipient_id' => $recipient->id ?? null, + 'error' => $exception->getMessage(), + ]); + $this->reportThrowable($exception); + } + } + + $this->safeAudit( + $operation . '_failure_alerted', + 'resource_reservation', + (int) ($snapshot['reservation_id'] ?? 0), + [ + 'service_id' => $snapshot['service_id'] ?? null, + 'invoice_id' => $snapshot['invoice_id'] ?? null, + 'attempts' => $snapshot['attempts'] ?? null, + ] + ); + } + + /** + * Notify operators when a paid resource upgrade exhausts automatic + * retries. ServiceUpgradeService persists its deduplication timestamp + * before this method is called. + * + * @param array $snapshot + */ + public function notifyUpgradeFailure(array $snapshot): void + { + $recipients = $this->getAdminRecipients(); + if ($recipients->isEmpty()) { + Log::critical( + 'Dynamic resource upgrade requires attention', + $snapshot + ); + } + + foreach ($recipients as $recipient) { + try { + $recipient->notify( + new ProvisioningFailedNotification($snapshot) + ); + } catch (\Throwable $exception) { + Log::error( + 'Failed to notify operator about dynamic upgrade failure', + [ + 'upgrade_id' => $snapshot['upgrade_id'] ?? null, + 'service_id' => $snapshot['service_id'] ?? null, + 'recipient_id' => $recipient->id ?? null, + 'error' => $exception->getMessage(), + ] + ); + $this->reportThrowable($exception); + } + } + + $reservationId = (int) ($snapshot['reservation_id'] ?? 0); + $this->safeAudit( + 'upgrade_failure_alerted', + $reservationId > 0 ? 'resource_reservation' : 'service_upgrade', + $reservationId > 0 + ? $reservationId + : (int) ($snapshot['upgrade_id'] ?? 0), + [ + 'upgrade_id' => $snapshot['upgrade_id'] ?? null, + 'service_id' => $snapshot['service_id'] ?? null, + 'invoice_id' => $snapshot['invoice_id'] ?? null, + 'reservation_id' => $snapshot['reservation_id'] ?? null, + 'attempts' => $snapshot['attempts'] ?? null, + 'error' => $snapshot['error'] ?? null, + ] + ); + } + + /** + * Notify operators that an external/partial payment exists but its + * capacity guarantee may no longer be consumed. + * + * @param array $snapshot + */ + public function notifyPaymentAttention(array $snapshot): void + { + $recipients = $this->getAdminRecipients(); + if ($recipients->isEmpty()) { + Log::critical('Capacity invoice payment requires refund review', $snapshot); + + return; + } + + foreach ($recipients as $recipient) { + try { + $recipient->notify(new PaymentAttentionNotification($snapshot)); + } catch (\Throwable $exception) { + Log::error('Failed to notify operator about a late capacity payment', [ + 'invoice_id' => $snapshot['invoice_id'] ?? null, + 'recipient_id' => $recipient->id ?? null, + 'error' => $exception->getMessage(), + ]); + $this->reportThrowable($exception); + } + } + } + /** * Get all admin users (non-null role_id = admin in Paymenter). */ diff --git a/Services/AllocationSelectionService.php b/Services/AllocationSelectionService.php new file mode 100644 index 0000000..5b47774 --- /dev/null +++ b/Services/AllocationSelectionService.php @@ -0,0 +1,240 @@ + $available + * @param list $requiredPorts + * @param list $allowedPortRanges + * @return list|null + */ + public function select( + array $available, + int $allocationCount, + array $requiredPorts = [], + array $allowedPortRanges = [], + bool $dedicatedIp = false + ): ?array { + if ($allocationCount < 1) { + throw new \InvalidArgumentException('At least one allocation is required.'); + } + + foreach ($requiredPorts as $requiredPort) { + if (! is_int($requiredPort) || $requiredPort < 1 || $requiredPort > 65535) { + throw new \InvalidArgumentException( + 'Required Pterodactyl ports must be integer values between 1 and 65535.' + ); + } + } + if (count(array_unique($requiredPorts)) !== count($requiredPorts)) { + throw new \InvalidArgumentException( + 'A required Pterodactyl port cannot be requested more than once.' + ); + } + if (count($requiredPorts) > $allocationCount) { + throw new \InvalidArgumentException( + 'Required ports cannot exceed the requested allocation count.' + ); + } + + foreach ($available as $allocation) { + if ( + ! is_int($allocation['id'] ?? null) + || $allocation['id'] < 1 + || ! is_string($allocation['ip'] ?? null) + || $allocation['ip'] === '' + || ! is_int($allocation['port'] ?? null) + || $allocation['port'] < 1 + || $allocation['port'] > 65535 + ) { + return null; + } + if ( + $dedicatedIp + && ! is_bool($allocation['ip_in_use'] ?? null) + ) { + return null; + } + } + $allowedPortRanges = $this->validatedRanges($allowedPortRanges); + + usort( + $available, + fn (array $left, array $right): int => + $left['id'] <=> $right['id'] + ); + + $ids = array_column($available, 'id'); + if (count(array_unique($ids)) !== count($ids)) { + return null; + } + + if ($dedicatedIp) { + $candidates = []; + $byIp = []; + foreach ($available as $allocation) { + $key = $this->canonicalIp($allocation['ip']); + $byIp[$key] ??= [ + 'in_use' => false, + 'allocations' => [], + ]; + $byIp[$key]['in_use'] = $byIp[$key]['in_use'] + || $allocation['ip_in_use']; + $byIp[$key]['allocations'][] = $allocation; + } + foreach ($byIp as $ipGroup) { + if ($ipGroup['in_use']) { + continue; + } + $selected = $this->selectFromPool( + $ipGroup['allocations'], + $allocationCount, + $requiredPorts, + $allowedPortRanges + ); + if ($selected !== null) { + $candidates[] = $selected; + } + } + usort( + $candidates, + fn (array $left, array $right): int => + min(array_column($left, 'id')) + <=> min(array_column($right, 'id')) + ); + + return $candidates[0] ?? null; + } + + return $this->selectFromPool( + $available, + $allocationCount, + $requiredPorts, + $allowedPortRanges + ); + } + + /** + * @param list $available + * @param list $requiredPorts + * @param list $allowedPortRanges + * @return list|null + */ + private function selectFromPool( + array $available, + int $allocationCount, + array $requiredPorts, + array $allowedPortRanges + ): ?array { + if (count($available) < $allocationCount) { + return null; + } + + $selected = []; + $selectedIds = []; + if ($allowedPortRanges !== []) { + $primary = collect($available)->first( + fn (array $allocation): bool => $this->portAllowed( + $allocation['port'], + $allowedPortRanges + ) + ); + if (! is_array($primary)) { + return null; + } + $selected[] = $primary; + $selectedIds[$primary['id']] = true; + } + foreach ($requiredPorts as $requiredPort) { + if (collect($selected)->contains( + fn (array $allocation): bool => + $allocation['port'] === $requiredPort + )) { + continue; + } + $matches = array_values(array_filter( + $available, + fn (array $allocation): bool => + $allocation['port'] === $requiredPort + && ! isset($selectedIds[$allocation['id']]) + )); + if ($matches === []) { + return null; + } + + $selected[] = $matches[0]; + $selectedIds[$matches[0]['id']] = true; + } + + foreach ($available as $allocation) { + if (count($selected) >= $allocationCount) { + break; + } + if (isset($selectedIds[$allocation['id']])) { + continue; + } + + $selected[] = $allocation; + $selectedIds[$allocation['id']] = true; + } + + return count($selected) === $allocationCount ? $selected : null; + } + + /** + * @param list $ranges + * @return list + */ + private function validatedRanges(array $ranges): array + { + foreach ($ranges as $range) { + if ( + ! is_array($range) + || ! is_int($range['from'] ?? null) + || ! is_int($range['to'] ?? null) + || $range['from'] < 1 + || $range['to'] > 65535 + || $range['from'] > $range['to'] + ) { + throw new \InvalidArgumentException( + 'Pterodactyl port ranges must be inclusive integer bounds between 1 and 65535.' + ); + } + } + + return array_values($ranges); + } + + /** + * @param list $ranges + */ + private function portAllowed(int $port, array $ranges): bool + { + foreach ($ranges as $range) { + if ($port >= $range['from'] && $port <= $range['to']) { + return true; + } + } + + return false; + } + + private function canonicalIp(string $ip): string + { + $packed = @inet_pton(trim($ip)); + + return $packed === false + ? strtolower(trim($ip)) + : bin2hex($packed); + } +} diff --git a/Services/ConfigOptionSetupService.php b/Services/ConfigOptionSetupService.php index cc3d20a..4be4320 100644 --- a/Services/ConfigOptionSetupService.php +++ b/Services/ConfigOptionSetupService.php @@ -2,9 +2,13 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Services; +use App\Helpers\ExtensionHelper; use App\Models\ConfigOption; -use App\Rules\DynamicSliderPricingRule; +use App\Models\Product; +use App\Rules\DynamicSliderMetadataRule; +use App\Support\PanelEndpointIdentity; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Schema; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\Concerns\AuditsExtensionActions; class ConfigOptionSetupService @@ -44,11 +48,30 @@ class ConfigOptionSetupService public function createDynamicSliderOptions(int $productId, array $config, array $locations = []): array { $created = DB::transaction(function () use ($productId, $config, $locations) { + $product = Product::query() + ->with(['plans.prices', 'settings', 'server']) + ->lockForUpdate() + ->findOrFail($productId); + $this->assertEligibleProduct($product); + $locations = $this->validatedLocations($product, $locations); + $this->validateSingleCurrency($product); + // Product is the shared first lock for quote readers and + // configuration writers. Retire only unbound cart quotes before + // guarded option/price mutations; invoice and upgrade commitments + // remain immutable and deliberately block the wizard. + $this->invalidateUnpaidReservations($productId); + $this->synchronizePlanBasePrice($product, $config); + + $product->allow_quantity = 'disabled'; + $product->save(); + $out = []; foreach (['memory', 'cpu', 'disk'] as $resourceType) { $enableKey = "enable_{$resourceType}_slider"; if (($config[$enableKey] ?? true) === false) { + $this->retireResourceOption($productId, $resourceType); + continue; } @@ -59,12 +82,13 @@ public function createDynamicSliderOptions(int $productId, array $config, array ); } - if (! empty($locations)) { - $out['location'] = $this->createLocationOption($productId, $locations); + $location = $this->synchronizeLocationOption($productId, $locations); + if ($location !== null) { + $out['location'] = $location; } return $out; - }); + }, 5); if (! empty($created)) { $this->safeAudit('setup_run', 'product_config', $productId, [ @@ -80,7 +104,12 @@ private function createResourceOption(int $productId, string $resourceType, arra { $defaults = $this->resourceDefaults[$resourceType] ?? []; - $metadata = $this->buildResourceMetadata($resourceType, $config, $defaults); + $metadata = $this->buildResourceMetadata( + $productId, + $resourceType, + $config, + $defaults + ); $existingOption = $this->findExistingOption($productId, $resourceType); @@ -88,6 +117,8 @@ private function createResourceOption(int $productId, string $resourceType, arra $existingOption->update([ 'type' => 'dynamic_slider', 'env_variable' => $resourceType, + 'hidden' => false, + 'upgradable' => true, 'metadata' => $metadata, ]); @@ -115,34 +146,61 @@ private function createResourceOption(int $productId, string $resourceType, arra return $option; } - private function buildResourceMetadata(string $resourceType, array $config, array $defaults): array + private function buildResourceMetadata( + int $productId, + string $resourceType, + array $config, + array $defaults + ): array { $pricingModel = $config['pricing_model'] ?? 'linear'; $divisor = $defaults['display_divisor'] ?? 1; $pricing = $this->buildPricingMetadata($resourceType, $pricingModel, $config); - $errors = []; - (new DynamicSliderPricingRule())->validate('metadata.pricing', $pricing, function (string $message) use (&$errors) { - $errors[] = $message; - }); - - if ($errors !== []) { - throw new \InvalidArgumentException(implode('; ', $errors)); - } - $metadata = [ + 'managed_by' => 'dynamic_pterodactyl', + 'managed_product_id' => $productId, 'resource_type' => $resourceType, - 'min' => (int) (($config["{$resourceType}_min"] ?? ($defaults['min'] / $divisor)) * $divisor), - 'max' => (int) (($config["{$resourceType}_max"] ?? ($defaults['max'] / $divisor)) * $divisor), - 'step' => (int) (($config["{$resourceType}_step"] ?? ($defaults['step'] / $divisor)) * $divisor), - 'default' => (int) (($config["{$resourceType}_default"] ?? ($defaults['default'] / $divisor)) * $divisor), + 'min' => $this->scaleDisplayValue( + $config["{$resourceType}_min"] ?? ($defaults['min'] / $divisor), + $divisor, + "{$resourceType} minimum" + ), + 'max' => $this->scaleDisplayValue( + $config["{$resourceType}_max"] ?? ($defaults['max'] / $divisor), + $divisor, + "{$resourceType} maximum" + ), + 'step' => $this->scaleDisplayValue( + $config["{$resourceType}_step"] ?? ($defaults['step'] / $divisor), + $divisor, + "{$resourceType} step" + ), + 'default' => $this->scaleDisplayValue( + $config["{$resourceType}_default"] ?? ($defaults['default'] / $divisor), + $divisor, + "{$resourceType} default" + ), 'unit' => $defaults['unit'], 'display_unit' => $defaults['display_unit'], 'display_divisor' => $defaults['display_divisor'], 'pricing' => $pricing, ]; + $errors = []; + (new DynamicSliderMetadataRule())->validate( + 'metadata', + $metadata, + function (string $message) use (&$errors): void { + $errors[] = $message; + } + ); + + if ($errors !== []) { + throw new \InvalidArgumentException(implode('; ', $errors)); + } + return $metadata; } @@ -150,34 +208,96 @@ private function buildPricingMetadata(string $resourceType, string $pricingModel { $pricing = [ 'model' => $pricingModel, - 'base_price' => (float) ($config['base_price'] ?? 0), ]; switch ($pricingModel) { case 'linear': - $pricing['rate_per_unit'] = (float) ($config["{$resourceType}_rate"] ?? 0); + $pricing['rate_per_unit'] = $this->nonNegativeDecimal( + $config["{$resourceType}_rate"] ?? 0, + "{$resourceType} rate" + ); break; case 'tiered': - $pricing['tiers'] = $config["{$resourceType}_tiers"] ?? []; + $pricing['tiers'] = collect( + $config["{$resourceType}_tiers"] ?? [] + )->values()->map(function ($tier, int $index) use ($resourceType): array { + if (! is_array($tier)) { + throw new \InvalidArgumentException( + ucfirst($resourceType).' pricing tiers must be arrays.' + ); + } + + return [ + 'up_to' => ($tier['up_to'] ?? null) === null + ? null + : $this->nonNegativeDecimal( + $tier['up_to'], + "{$resourceType} tier ".($index + 1).' limit' + ), + 'rate' => $this->nonNegativeDecimal( + $tier['rate'] ?? null, + "{$resourceType} tier ".($index + 1).' rate' + ), + ]; + })->all(); break; case 'base_addon': - $pricing['included_units'] = (float) ($config["{$resourceType}_included"] ?? 0); - $pricing['overage_rate'] = (float) ($config["{$resourceType}_overage"] ?? 0); + $pricing['included_units'] = $this->nonNegativeDecimal( + $config["{$resourceType}_included"] ?? 0, + "{$resourceType} included units" + ); + $pricing['overage_rate'] = $this->nonNegativeDecimal( + $config["{$resourceType}_overage"] ?? 0, + "{$resourceType} overage rate" + ); break; + + default: + throw new \InvalidArgumentException( + 'Unknown dynamic resource pricing model.' + ); } return $pricing; } - private function createLocationOption(int $productId, array $locations): ConfigOption + private function synchronizeLocationOption(int $productId, array $locations): ?ConfigOption { - $existingLocation = $this->findExistingOption($productId, 'location'); + $existingLocation = $this->findExistingOption( + $productId, + 'location', + $locations !== [] + ); + + if ($locations === []) { + if ($existingLocation !== null) { + $existingLocation->update([ + 'hidden' => true, + 'upgradable' => false, + ]); + $existingLocation->children()->update(['hidden' => true]); + } + + return null; + } if ($existingLocation) { $locationOption = $existingLocation; - $locationOption->update(['env_variable' => 'location']); + $locationOption->update([ + 'env_variable' => 'location', + 'hidden' => false, + 'upgradable' => false, + 'metadata' => array_merge( + (array) ($locationOption->metadata ?? []), + [ + 'managed_by' => 'dynamic_pterodactyl', + 'managed_product_id' => $productId, + 'resource_type' => 'location', + ] + ), + ]); } else { $locationOption = ConfigOption::create([ 'name' => 'Location', @@ -186,12 +306,24 @@ private function createLocationOption(int $productId, array $locations): ConfigO 'hidden' => false, 'sort' => 0, 'parent_id' => null, + 'upgradable' => false, + 'metadata' => [ + 'managed_by' => 'dynamic_pterodactyl', + 'managed_product_id' => $productId, + 'resource_type' => 'location', + ], ]); $locationOption->products()->syncWithoutDetaching([$productId]); } + $selectedLocationIds = []; foreach ($locations as $loc) { + if (! isset($loc['id']) || ! is_numeric($loc['id'])) { + throw new \InvalidArgumentException('Every selected location must have a numeric Pterodactyl ID.'); + } + + $selectedLocationIds[] = (string) $loc['id']; $locationName = $loc['long'] ?: $loc['short']; ConfigOption::updateOrCreate([ 'parent_id' => $locationOption->id, @@ -201,28 +333,82 @@ private function createLocationOption(int $productId, array $locations): ConfigO 'type' => 'option', 'hidden' => false, 'sort' => 0, + 'metadata' => [ + 'managed_by' => 'dynamic_pterodactyl', + 'managed_product_id' => $productId, + 'managed_location_id' => (int) $loc['id'], + ], ]); } + $locationOption->children() + ->whereNotIn('env_variable', $selectedLocationIds) + ->update(['hidden' => true]); + return $locationOption; } + private function retireResourceOption(int $productId, string $resourceType): void + { + $option = $this->findExistingOption($productId, $resourceType, false); + if ($option === null) { + return; + } + + $option->update([ + 'hidden' => true, + 'upgradable' => false, + ]); + } + + private function synchronizePlanBasePrice(Product $product, array $config): void + { + $monthlyBase = $this->nonNegativeDecimal( + $config['base_price'] ?? 0, + 'monthly base price' + ); + + foreach ($product->plans as $plan) { + $multiplier = match ($plan->billing_unit) { + 'day' => (int) $plan->billing_period / 30, + 'week' => (int) $plan->billing_period / 4, + 'year' => (int) $plan->billing_period * 12, + default => max(1, (int) $plan->billing_period), + }; + + $plan->dynamic_slider_base_price = round($monthlyBase * $multiplier, 2); + $plan->save(); + } + } + + private function validateSingleCurrency(Product $product): void + { + $currencies = $product->plans + ->flatMap(fn ($plan) => $plan->prices->pluck('currency_code')) + ->filter() + ->unique() + ->values(); + + if ($currencies->count() > 1) { + throw new \InvalidArgumentException( + 'Dynamic slider pricing currently supports one product currency. Configure separate products for each currency.' + ); + } + } + public function checkExistingOptions(int $productId): array { $resourceTypes = ['memory', 'cpu', 'disk']; - $existing = DB::table('config_options') - ->join('config_option_products', 'config_options.id', '=', 'config_option_products.config_option_id') - ->where('config_option_products.product_id', $productId) - ->where('config_options.type', 'dynamic_slider') - ->whereNull('config_options.parent_id') - ->get(['config_options.id', 'config_options.name', 'config_options.metadata']); - $existingTypes = []; - foreach ($existing as $option) { - $metadata = json_decode($option->metadata, true); - $resourceType = $metadata['resource_type'] ?? strtolower($option->name); - if (in_array($resourceType, $resourceTypes)) { + foreach ($this->productOptions($productId) as $option) { + $metadata = (array) ($option->metadata ?? []); + $resourceType = strtolower((string) ($metadata['resource_type'] ?? '')); + if ( + $option->type === 'dynamic_slider' + && ($metadata['managed_by'] ?? null) === 'dynamic_pterodactyl' + && in_array($resourceType, $resourceTypes, true) + ) { $existingTypes[$resourceType] = $option->id; } } @@ -234,19 +420,327 @@ public function checkExistingOptions(int $productId): array ]; } - private function findExistingOption(int $productId, string $name): ?ConfigOption + private function findExistingOption( + int $productId, + string $name, + bool $failOnConflict = true + ): ?ConfigOption { - $result = DB::table('config_options') - ->join('config_option_products', 'config_options.id', '=', 'config_option_products.config_option_id') - ->where('config_option_products.product_id', $productId) - ->where(function ($query) use ($name) { - $query->whereRaw('LOWER(config_options.name) = ?', [strtolower($name)]) - ->orWhereRaw("JSON_UNQUOTE(JSON_EXTRACT(config_options.metadata, '$.resource_type')) = ?", [$name]); + $name = strtolower($name); + $candidates = $this->productOptions($productId) + ->filter(function (ConfigOption $option) use ($name): bool { + $metadata = (array) ($option->metadata ?? []); + + return ($metadata['managed_by'] ?? null) === 'dynamic_pterodactyl' + && ( + strtolower((string) ($metadata['resource_type'] ?? '')) === $name + || ( + $name === 'location' + && strtolower((string) $option->env_variable) === 'location' + ) + ); }) - ->whereNull('config_options.parent_id') - ->first(); + ->values(); + + if ($candidates->count() > 1) { + throw new \InvalidArgumentException( + "This product has multiple Dynamic Pterodactyl {$name} options." + ); + } + if ($candidates->count() === 1) { + $option = $candidates->first(); + $metadata = (array) ($option->metadata ?? []); + $owner = $metadata['managed_product_id'] ?? null; + if ($owner !== null && (int) $owner !== $productId) { + throw new \InvalidArgumentException( + "The managed {$name} option belongs to a different product." + ); + } + + // One-time adoption of options created by an earlier plugin version + // is permitted only when the explicit managed_by marker is present. + if ($owner === null) { + $option->metadata = array_merge($metadata, [ + 'managed_product_id' => $productId, + 'resource_type' => $name, + ]); + $option->save(); + } - return $result ? ConfigOption::find($result->id) : null; + return $option; + } + + $conflict = $this->productOptions($productId)->first( + fn (ConfigOption $option): bool => strtolower((string) $option->env_variable) === $name + || strtolower((string) $option->name) === $name + ); + if ($conflict !== null && $failOnConflict) { + throw new \InvalidArgumentException( + "An unmanaged {$name} configuration option already exists. Rename or remove it before running this wizard." + ); + } + + return null; + } + + private function productOptions(int $productId) + { + return ConfigOption::query() + ->whereNull('parent_id') + ->whereHas( + 'products', + fn ($query) => $query->whereKey($productId) + ) + ->get(); + } + + private function assertEligibleProduct(Product $product): void + { + if ($product->hidden) { + throw new \InvalidArgumentException( + 'Dynamic stock cannot be configured on a hidden product.' + ); + } + if ( + $product->server === null + || ! $product->server->enabled + || $product->server->extension !== 'Pterodactyl' + ) { + throw new \InvalidArgumentException( + 'Dynamic stock requires an enabled Pterodactyl server extension.' + ); + } + + $settings = ExtensionHelper::settingsToArray( + $product->server->settings + ); + $host = trim((string) ($settings['host'] ?? '')); + try { + $panelIdentity = PanelEndpointIdentity::hash($host); + } catch (\InvalidArgumentException) { + $panelIdentity = ''; + } + if ( + $panelIdentity === '' + || ! hash_equals( + app(PterodactylInventoryService::class)->panelIdentity(), + $panelIdentity + ) + ) { + throw new \InvalidArgumentException( + 'The product provisioner and Dynamic Pterodactyl stock service must target the same panel.' + ); + } + } + + /** + * Re-resolve every selected location from the authoritative panel. When no + * customer choice is configured, the product must have one static location. + * + * @return list + */ + private function validatedLocations(Product $product, array $locations): array + { + $available = collect(app(PterodactylInventoryService::class)->locations()) + ->keyBy('id'); + + if ($locations !== []) { + $validated = []; + foreach ($locations as $location) { + $id = is_array($location) + ? ($location['id'] ?? null) + : null; + if (! is_int($id) && ! ( + is_string($id) + && preg_match('/^[1-9]\d*$/D', $id) === 1 + )) { + throw new \InvalidArgumentException( + 'Every selected location must have a positive integer ID.' + ); + } + + $authoritative = $available->get((int) $id); + if (! is_array($authoritative)) { + throw new \InvalidArgumentException( + 'A selected location no longer exists in Pterodactyl.' + ); + } + $validated[(int) $id] = $authoritative; + } + + return array_values($validated); + } + + $raw = $product->settings + ->firstWhere('key', 'location_ids') + ?->value; + $ids = is_array($raw) ? $raw : [$raw]; + $ids = collect($ids) + ->filter(fn ($id): bool => $id !== null && $id !== '') + ->map(function ($id): int { + if (! is_int($id) && ! ( + is_string($id) + && preg_match('/^[1-9]\d*$/D', $id) === 1 + )) { + throw new \InvalidArgumentException( + 'The product static location must be a positive integer.' + ); + } + + return (int) $id; + }) + ->unique() + ->values(); + + if ($ids->count() !== 1 || ! $available->has($ids->first())) { + throw new \InvalidArgumentException( + 'Select customer locations or configure exactly one valid static Pterodactyl location on the product.' + ); + } + + return []; + } + + private function scaleDisplayValue( + mixed $value, + int $divisor, + string $label + ): int { + if ($divisor <= 0) { + throw new \InvalidArgumentException( + "The {$label} display divisor is invalid." + ); + } + + $text = is_int($value) || is_float($value) + ? (string) $value + : (is_string($value) ? $value : ''); + if ( + preg_match('/^(0|[1-9]\d*)(?:\.(\d+))?$/D', $text, $matches) !== 1 + ) { + throw new \InvalidArgumentException( + "The {$label} must be a non-negative decimal without exponent notation." + ); + } + + $whole = filter_var( + $matches[1], + FILTER_VALIDATE_INT, + FILTER_NULL_ON_FAILURE + ); + if ($whole === null || $whole > intdiv(PHP_INT_MAX, $divisor)) { + throw new \InvalidArgumentException( + "The {$label} is outside the supported range." + ); + } + + $scaled = $whole * $divisor; + $fraction = $matches[2] ?? ''; + if ($fraction === '') { + return $scaled; + } + if (strlen($fraction) > 18) { + throw new \InvalidArgumentException( + "The {$label} has more precision than the internal unit supports." + ); + } + + $denominator = 10 ** strlen($fraction); + $numerator = (int) $fraction; + if ($numerator > intdiv(PHP_INT_MAX, $divisor)) { + throw new \InvalidArgumentException( + "The {$label} is outside the supported range." + ); + } + $fractionProduct = $numerator * $divisor; + if ($fractionProduct % $denominator !== 0) { + throw new \InvalidArgumentException( + "The {$label} cannot be represented exactly in internal resource units." + ); + } + + $fractionScaled = intdiv($fractionProduct, $denominator); + if ($scaled > PHP_INT_MAX - $fractionScaled) { + throw new \InvalidArgumentException( + "The {$label} is outside the supported range." + ); + } + + return $scaled + $fractionScaled; + } + + private function nonNegativeDecimal(mixed $value, string $label): float + { + $text = is_int($value) || is_float($value) + ? (string) $value + : (is_string($value) ? $value : ''); + if ( + preg_match('/^(0|[1-9]\d*)(?:\.\d+)?$/D', $text) !== 1 + || ! is_finite((float) $text) + || (float) $text < 0 + ) { + throw new \InvalidArgumentException( + "The {$label} must be a finite non-negative decimal without exponent notation." + ); + } + + return (float) $text; + } + + private function invalidateUnpaidReservations(int $productId): void + { + $candidateQuery = DB::table('ptero_resource_reservations') + ->where('product_id', $productId) + ->where('status', 'pending') + ->whereNull('service_id') + ->whereNull('invoice_id'); + if (Schema::hasColumn('ptero_resource_reservations', 'service_upgrade_id')) { + $candidateQuery->whereNull('service_upgrade_id'); + } + $candidateIds = $candidateQuery->orderBy('id')->pluck('id'); + + foreach ($candidateIds as $candidateId) { + $reservation = DB::table('ptero_resource_reservations') + ->where('id', $candidateId) + ->lockForUpdate() + ->first(); + if ( + $reservation === null + || $reservation->status !== 'pending' + || (int) $reservation->product_id !== $productId + || $reservation->service_id !== null + || $reservation->invoice_id !== null + || ( + property_exists($reservation, 'service_upgrade_id') + && $reservation->service_upgrade_id !== null + ) + ) { + continue; + } + + $updates = [ + 'status' => 'cancelled', + 'admin_notes' => 'Unbound cart quote invalidated after dynamic product configuration changed.', + 'updated_at' => now(), + ]; + if (Schema::hasColumn('ptero_resource_reservations', 'upgrade_guard_id')) { + $updates['upgrade_guard_id'] = null; + } + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->where('status', 'pending') + ->update($updates); + + if (Schema::hasTable('ptero_reservation_allocations')) { + DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservation->id) + ->whereNull('released_at') + ->update([ + 'released_at' => now(), + 'updated_at' => now(), + ]); + } + } } public static function getProductsWithSlidersCount(): int @@ -254,6 +748,7 @@ public static function getProductsWithSlidersCount(): int return DB::table('config_options') ->join('config_option_products', 'config_options.id', '=', 'config_option_products.config_option_id') ->where('config_options.type', 'dynamic_slider') + ->where('config_options.hidden', false) ->whereNull('config_options.parent_id') ->distinct('config_option_products.product_id') ->count('config_option_products.product_id'); diff --git a/Services/LegacyReservationReadinessService.php b/Services/LegacyReservationReadinessService.php new file mode 100644 index 0000000..2fa4f47 --- /dev/null +++ b/Services/LegacyReservationReadinessService.php @@ -0,0 +1,43 @@ + + * }> + */ + public function blockers(): array + { + return $this->gate()->blockers(); + } + + public function assertReady(): void + { + $this->gate()->assertReady(); + } + + private function gate(): object + { + $gate = require dirname(__DIR__).'/migration-readiness.php'; + if (! is_object($gate) || ! method_exists($gate, 'assertReady')) { + throw new \RuntimeException( + 'Dynamic Pterodactyl migration readiness hook is invalid.' + ); + } + + return $gate; + } +} diff --git a/Services/NodeSelectionService.php b/Services/NodeSelectionService.php index 8d84ec1..58445f0 100644 --- a/Services/NodeSelectionService.php +++ b/Services/NodeSelectionService.php @@ -6,25 +6,46 @@ class NodeSelectionService { private ResourceCalculationService $resourceService; - public function __construct(ResourceCalculationService $resourceService) - { + public function __construct( + ResourceCalculationService $resourceService, + private readonly AllocationSelectionService $allocations + ) { $this->resourceService = $resourceService; } /** - * Select the best node for given resource requirements - * - * Algorithm: memory/disk headroom weighting. + * Select an eligible node and one primary Pterodactyl allocation. * - * Pterodactyl does not expose authoritative node CPU capacity, so CPU is - * passed through as a server limit but is never treated as hard inventory. + * @param array{memory: int, cpu: int, disk: int} $requirements */ public function selectBestNode( int $locationId, array $requirements, ?string $excludeReservationToken = null - ): ?array - { + ): ?array { + return $this->selectBestNodeWithAllocations( + $locationId, + $requirements, + 1, + $excludeReservationToken + ); + } + + /** + * Select an eligible node and the exact free allocations that should be + * locked by the reservation transaction. + * + * @param array{memory: int, cpu: int, disk: int} $requirements + */ + public function selectBestNodeWithAllocations( + int $locationId, + array $requirements, + int $allocationCount = 1, + ?string $excludeReservationToken = null, + array $requiredPorts = [], + array $allowedPortRanges = [], + bool $dedicatedIp = false + ): ?array { $locationData = $this->resourceService->getLocationAvailability( $locationId, $excludeReservationToken @@ -33,36 +54,47 @@ public function selectBestNode( $candidates = []; foreach ($locationData['nodes'] as $node) { - // Skip nodes in maintenance mode - if ($node['maintenance_mode'] ?? false) { + if (! ($node['eligible'] ?? false)) { continue; } - // Check if node can accommodate requirements - if ($node['available']['memory'] < $requirements['memory']) { - continue; - } - if ($node['available']['disk'] < $requirements['disk']) { + $selectedAllocations = $this->allocations->select( + $node['available_allocations'] ?? [], + $allocationCount, + $requiredPorts, + $allowedPortRanges, + $dedicatedIp + ); + if ($selectedAllocations === null) { continue; } - // Calculate remaining headroom after allocation - $remainingMemory = $node['available']['memory'] - $requirements['memory']; - $remainingDisk = $node['available']['disk'] - $requirements['disk']; + foreach (['memory', 'cpu', 'disk'] as $resource) { + if ( + ! isset($requirements[$resource]) + || ! is_int($requirements[$resource]) + || $requirements[$resource] < 1 + || (int) ($node['available'][$resource] ?? -1) < $requirements[$resource] + ) { + continue 2; + } + } - $memoryScore = ($remainingMemory / max(1, $node['total']['memory'])) * 0.60; - $diskScore = ($remainingDisk / max(1, $node['total']['disk'])) * 0.40; + $remaining = [ + 'memory' => $node['available']['memory'] - $requirements['memory'], + 'cpu' => $node['available']['cpu'] - $requirements['cpu'], + 'disk' => $node['available']['disk'] - $requirements['disk'], + ]; - $score = $memoryScore + $diskScore; + $score = ($remaining['memory'] / max(1, $node['total']['memory'])) * 0.50 + + ($remaining['cpu'] / max(1, $node['total']['cpu'])) * 0.15 + + ($remaining['disk'] / max(1, $node['total']['disk'])) * 0.35; + $node['selected_allocations'] = $selectedAllocations; $candidates[] = [ 'node' => $node, 'score' => $score, - 'remaining' => [ - 'memory' => $remainingMemory, - 'cpu' => null, - 'disk' => $remainingDisk, - ], + 'remaining' => $remaining, ]; } @@ -70,8 +102,13 @@ public function selectBestNode( return null; } - // Sort by score descending, return highest - usort($candidates, fn ($a, $b) => $b['score'] <=> $a['score']); + usort($candidates, function (array $left, array $right): int { + $score = $right['score'] <=> $left['score']; + + return $score !== 0 + ? $score + : $left['node']['node_id'] <=> $right['node']['node_id']; + }); return $candidates[0]['node']; } diff --git a/Services/ProductResourceConfigurationService.php b/Services/ProductResourceConfigurationService.php new file mode 100644 index 0000000..b7a7cc8 --- /dev/null +++ b/Services/ProductResourceConfigurationService.php @@ -0,0 +1,679 @@ +inventory = $inventory ?? app(PterodactylInventoryService::class); + } + + /** + * Resolve and strictly validate the complete resource vector represented by + * a product and the customer's current configuration. + * + * @param array $submittedOptions + * @return array{ + * product_id: int, + * location_id: int, + * resources: array{memory: int, cpu: int, disk: int}, + * sliders: array, + * allocation_count: int, + * required_ports: list, + * allocation_mappings: list, + * allowed_port_ranges: list, + * dedicated_ip: bool + * } + */ + public function forQuote(Product $product, array $submittedOptions): array + { + if (DB::transactionLevel() === 0) { + return DB::transaction( + fn (): array => $this->forQuote( + $product, + $submittedOptions + ), + 5 + ); + } + + $product = app(CapacityConfigurationLockService::class) + ->lockProduct((int) $product->id); + $product->loadMissing([ + 'settings', + 'server.settings', + ]); + + if ($product->server === null || $product->server->extension !== 'Pterodactyl') { + throw new InvalidStockConfigurationException( + 'This product does not use the Pterodactyl server extension.' + ); + } + + $provisioningUrl = $this->normalizePanelUrl((string) ( + $product->server->settings?->firstWhere('key', 'host')?->value ?? '' + )); + if ( + $provisioningUrl === '' + || ! hash_equals( + $this->inventory->panelIdentity(), + hash('sha256', $provisioningUrl) + ) + ) { + throw new InvalidStockConfigurationException( + 'The product and stock service are not configured for the same Pterodactyl panel.' + ); + } + $this->inventory->assertExclusiveProvisioningControl(); + + $selected = $this->normalizeSubmittedOptions($submittedOptions); + $activeOptions = $this->activeProductOptions($product); + if (array_diff(array_keys($selected), $activeOptions->modelKeys()) !== []) { + throw new InvalidResourceSelectionException( + 'A submitted configuration option is not available for this product.' + ); + } + + $settings = $product->settings + ->mapWithKeys(fn ($setting): array => [ + strtolower((string) $setting->key) => $setting->value, + ]); + if (! in_array($settings->get('node'), [null, '', 0, '0'], true)) { + throw new InvalidStockConfigurationException( + 'Dynamic stock products must not be pinned to a Pterodactyl node.' + ); + } + if (trim((string) ($settings->get('cpu_pinning') ?? '')) !== '') { + throw new InvalidStockConfigurationException( + 'Dynamic CPU stock cannot be combined with static CPU pinning.' + ); + } + $resources = []; + $sliders = []; + $locationId = null; + + foreach ($activeOptions as $option) { + $resource = strtolower((string) $option->getMetadata('resource_type', '')); + + if ($option->type === 'dynamic_slider' && in_array( + $resource, + ['memory', 'cpu', 'disk'], + true + )) { + if (isset($sliders[$resource])) { + throw new InvalidStockConfigurationException( + "The product has more than one {$resource} slider." + ); + } + + $slider = $this->sliderConfiguration($option); + $value = array_key_exists((int) $option->id, $selected) + ? $this->selectionInteger( + $selected[(int) $option->id], + "{$resource} selection" + ) + : $slider['default']; + + if ( + $value < $slider['min'] + || $value > $slider['max'] + || (($value - $slider['min']) % $slider['step']) !== 0 + ) { + throw new InvalidResourceSelectionException( + "The selected {$resource} value is outside its allowed range or step." + ); + } + + $resources[$resource] = $value; + $sliders[$resource] = $slider; + } + + if ($this->isLocationOption($option)) { + if ($locationId !== null) { + throw new InvalidStockConfigurationException( + 'The product has more than one location option.' + ); + } + + $locationId = $this->selectedLocation($option, $selected); + } + } + + foreach (['memory', 'cpu', 'disk'] as $resource) { + if (isset($resources[$resource])) { + continue; + } + + $resources[$resource] = $this->positiveConfigurationInteger( + $settings->get($resource), + "product {$resource}" + ); + } + + if ($sliders === []) { + throw new InvalidStockConfigurationException( + 'This product does not have a dynamic resource slider.' + ); + } + + $locationId ??= $this->staticLocation($settings->get('location_ids')); + + $portArray = $settings->get('port_array'); + $dedicatedIp = $this->configurationBoolean( + $settings->get('dedicated_ip'), + 'dedicated IP' + ); + $allowedPortRanges = $this->portRanges( + $settings->get('port_range') + ); + if ( + $portArray !== null + && $portArray !== '' + && ($dedicatedIp || $allowedPortRanges !== []) + ) { + throw new InvalidStockConfigurationException( + 'A product cannot combine a port array with dedicated IP or port-range deployment.' + ); + } + $additionalAllocations = $this->nonNegativeConfigurationInteger( + $settings->get('additional_allocations') ?? 0, + 'additional allocations' + ); + if ($additionalAllocations > 100) { + throw new InvalidStockConfigurationException( + 'A product cannot reserve more than 100 additional allocations.' + ); + } + $allocationRequirements = $this->allocationRequirements( + $portArray, + $additionalAllocations + ); + + return [ + 'product_id' => (int) $product->id, + 'location_id' => $locationId, + 'resources' => [ + 'memory' => $resources['memory'], + 'cpu' => $resources['cpu'], + 'disk' => $resources['disk'], + ], + 'sliders' => $sliders, + 'allocation_count' => $allocationRequirements['count'], + 'required_ports' => $allocationRequirements['ports'], + 'allocation_mappings' => $allocationRequirements['mappings'], + 'allowed_port_ranges' => $allowedPortRanges, + 'dedicated_ip' => $dedicatedIp, + ]; + } + + /** + * Resolve the current database truth instead of trusting a possibly stale + * eager-loaded relation. Retired wizard options remain attached for + * historical services, but hidden options and child values are not active + * customer inputs. + * + * @return Collection + */ + private function activeProductOptions(Product $product): Collection + { + return ConfigOption::query() + ->whereHas( + 'products', + fn ($query) => $query->whereKey($product->getKey()) + ) + ->where('hidden', false) + ->whereNull('parent_id') + ->orderBy('sort') + ->orderByDesc('id') + ->get(); + } + + /** + * @return array{config_option_id: int, min: int, max: int, step: int, default: int} + */ + private function sliderConfiguration(ConfigOption $option): array + { + $minimum = $this->positiveConfigurationInteger( + $option->getMetadata('min'), + "{$option->name} minimum" + ); + $maximum = $this->positiveConfigurationInteger( + $option->getMetadata('max'), + "{$option->name} maximum" + ); + $step = $this->positiveConfigurationInteger( + $option->getMetadata('step'), + "{$option->name} step" + ); + $default = $this->positiveConfigurationInteger( + $option->getMetadata('default'), + "{$option->name} default" + ); + + if ( + $maximum < $minimum + || (($maximum - $minimum) % $step) !== 0 + || $default < $minimum + || $default > $maximum + || (($default - $minimum) % $step) !== 0 + ) { + throw new InvalidStockConfigurationException( + "The {$option->name} slider metadata is inconsistent." + ); + } + + return [ + 'config_option_id' => (int) $option->id, + 'min' => $minimum, + 'max' => $maximum, + 'step' => $step, + 'default' => $default, + ]; + } + + /** + * @param array $selected + */ + private function selectedLocation(ConfigOption $option, array $selected): int + { + if (! array_key_exists((int) $option->id, $selected)) { + throw new InvalidResourceSelectionException( + 'A deployment location must be selected.' + ); + } + + $childId = $this->selectionInteger( + $selected[(int) $option->id], + 'location selection' + ); + $child = $option->availableChildren()->whereKey($childId)->first(); + if ($child === null) { + throw new InvalidResourceSelectionException( + 'The selected deployment location is not available for this product.' + ); + } + + return $this->positiveConfigurationInteger( + $child->env_variable, + 'Pterodactyl location ID' + ); + } + + private function isLocationOption(ConfigOption $option): bool + { + return strtolower(trim((string) $option->env_variable)) === 'location' + || strtolower(trim((string) $option->name)) === 'location'; + } + + private function staticLocation(mixed $rawLocations): int + { + if (is_string($rawLocations)) { + $decoded = json_decode($rawLocations, true); + $rawLocations = json_last_error() === JSON_ERROR_NONE + ? $decoded + : $rawLocations; + } + + $locations = is_array($rawLocations) ? array_values($rawLocations) : [$rawLocations]; + if (count($locations) !== 1) { + throw new InvalidStockConfigurationException( + 'Products without a location option must have exactly one static location.' + ); + } + + return $this->positiveConfigurationInteger( + $locations[0], + 'static Pterodactyl location' + ); + } + + /** + * @return array{ + * count: int, + * ports: list, + * mappings: list + * } + */ + private function allocationRequirements( + mixed $raw, + int $additionalAllocations = 0 + ): array + { + if ($raw === null || $raw === '') { + $mappings = [[ + 'environment_key' => 'SERVER_PORT', + 'requested_port' => null, + 'is_primary' => true, + ]]; + for ($index = 0; $index < $additionalAllocations; $index++) { + $mappings[] = [ + 'environment_key' => 'NONE', + 'requested_port' => null, + 'is_primary' => false, + ]; + } + + return [ + 'count' => count($mappings), + 'ports' => [], + 'mappings' => $mappings, + ]; + } + + if (! is_string($raw)) { + throw new InvalidStockConfigurationException( + 'The product port mapping is invalid.' + ); + } + + $decoded = json_decode($raw, true); + if (! is_array($decoded) || $decoded === []) { + throw new InvalidStockConfigurationException( + 'The product port mapping is invalid.' + ); + } + + $count = 0; + $environmentKeys = []; + $requestedPorts = []; + $mappings = []; + foreach ($decoded as $environmentKey => $ports) { + if ( + ! is_string($environmentKey) + || preg_match('/^[A-Z][A-Z0-9_]*$/', $environmentKey) !== 1 + || isset($environmentKeys[strtoupper($environmentKey)]) + ) { + throw new InvalidStockConfigurationException( + 'The product port mapping contains a duplicate or malformed environment key.' + ); + } + $environmentKeys[strtoupper($environmentKey)] = true; + + $ports = is_array($ports) ? array_values($ports) : [$ports]; + if ( + strtoupper($environmentKey) !== 'NONE' + && count($ports) !== 1 + ) { + throw new InvalidStockConfigurationException( + "The product port mapping may assign exactly one port to {$environmentKey}. " + .'Use NONE or additional allocations for unbound ports.' + ); + } + foreach ($ports as $index => $port) { + $port = $this->positiveConfigurationInteger($port, 'port mapping'); + if ($port > 65535) { + throw new InvalidStockConfigurationException( + 'The product port mapping contains an invalid port.' + ); + } + if (isset($requestedPorts[$port])) { + throw new InvalidStockConfigurationException( + 'The product port mapping cannot request the same port more than once.' + ); + } + $requestedPorts[$port] = true; + $mappings[] = [ + 'environment_key' => $environmentKey, + 'requested_port' => $port, + 'is_primary' => $environmentKey === 'SERVER_PORT' && $index === 0, + ]; + $count++; + } + } + + if (! isset($environmentKeys['SERVER_PORT'])) { + throw new InvalidStockConfigurationException( + 'The product port mapping must define SERVER_PORT.' + ); + } + for ($index = 0; $index < $additionalAllocations; $index++) { + $mappings[] = [ + 'environment_key' => 'NONE', + 'requested_port' => null, + 'is_primary' => false, + ]; + $count++; + } + + return [ + 'count' => max(1, $count), + 'ports' => array_map('intval', array_keys($requestedPorts)), + 'mappings' => $mappings, + ]; + } + + /** + * @return list + */ + private function portRanges(mixed $raw): array + { + if ($raw === null || $raw === '' || $raw === []) { + return []; + } + + if (is_string($raw)) { + $decoded = json_decode($raw, true); + $raw = json_last_error() === JSON_ERROR_NONE + ? $decoded + : explode(',', $raw); + } + if (! is_array($raw) || ! array_is_list($raw)) { + throw new InvalidStockConfigurationException( + 'The product port-range configuration must be a list.' + ); + } + + $ranges = []; + foreach ($raw as $range) { + if ( + ! is_string($range) + || preg_match( + '/^\s*(\d{1,5})(?:\s*-\s*(\d{1,5}))?\s*$/', + $range, + $matches + ) !== 1 + ) { + throw new InvalidStockConfigurationException( + 'Each product port range must be a port or inclusive start-end pair.' + ); + } + $from = (int) $matches[1]; + $to = isset($matches[2]) && $matches[2] !== '' + ? (int) $matches[2] + : $from; + if ($from < 1 || $to > 65535 || $from > $to) { + throw new InvalidStockConfigurationException( + 'Each product port range must stay between 1 and 65535.' + ); + } + $ranges[] = ['from' => $from, 'to' => $to]; + } + + usort( + $ranges, + fn (array $left, array $right): int => + [$left['from'], $left['to']] <=> [$right['from'], $right['to']] + ); + $merged = []; + foreach ($ranges as $range) { + $last = array_key_last($merged); + if ( + $last !== null + && $range['from'] <= $merged[$last]['to'] + 1 + ) { + $merged[$last]['to'] = max( + $merged[$last]['to'], + $range['to'] + ); + + continue; + } + $merged[] = $range; + } + + return $merged; + } + + private function configurationBoolean(mixed $value, string $field): bool + { + if ($value === null || $value === '') { + return false; + } + if (is_bool($value)) { + return $value; + } + if (is_int($value) && ($value === 0 || $value === 1)) { + return $value === 1; + } + if (is_string($value)) { + $normalized = strtolower(trim($value)); + if (in_array($normalized, ['0', 'false', 'off', 'no'], true)) { + return false; + } + if (in_array($normalized, ['1', 'true', 'on', 'yes'], true)) { + return true; + } + } + + throw new InvalidStockConfigurationException( + "The {$field} configuration must be a boolean." + ); + } + + /** + * Accept Paymenter's list of {option_id,value} entries and the keyed map + * emitted by the quote client. + * + * @param array $submitted + * @return array + */ + private function normalizeSubmittedOptions(array $submitted): array + { + $normalized = []; + + if (array_is_list($submitted)) { + foreach ($submitted as $entry) { + if (! is_array($entry) || ! array_key_exists('option_id', $entry)) { + throw new InvalidResourceSelectionException( + 'Configuration options must identify an option and value.' + ); + } + + $optionId = $this->selectionInteger( + $entry['option_id'], + 'configuration option ID' + ); + if (array_key_exists($optionId, $normalized)) { + throw new InvalidResourceSelectionException( + 'A configuration option cannot be submitted more than once.' + ); + } + $normalized[$optionId] = $entry['value'] ?? null; + } + + return $normalized; + } + + foreach ($submitted as $optionId => $value) { + $normalized[$this->selectionInteger( + $optionId, + 'configuration option ID' + )] = $value; + } + + return $normalized; + } + + private function positiveConfigurationInteger(mixed $value, string $field): int + { + try { + $value = $this->strictInteger($value); + } catch (\InvalidArgumentException) { + throw new InvalidStockConfigurationException( + "The {$field} configuration must be an integer." + ); + } + + if ($value <= 0) { + throw new InvalidStockConfigurationException( + "The {$field} configuration must be positive." + ); + } + + return $value; + } + + private function nonNegativeConfigurationInteger(mixed $value, string $field): int + { + try { + $value = $this->strictInteger($value); + } catch (\InvalidArgumentException) { + throw new InvalidStockConfigurationException( + "The {$field} configuration must be an integer." + ); + } + + if ($value < 0) { + throw new InvalidStockConfigurationException( + "The {$field} configuration cannot be negative." + ); + } + + return $value; + } + + private function selectionInteger(mixed $value, string $field): int + { + try { + return $this->strictInteger($value); + } catch (\InvalidArgumentException) { + throw new InvalidResourceSelectionException( + "The {$field} must be an integer." + ); + } + } + + private function strictInteger(mixed $value): int + { + if (is_int($value)) { + return $value; + } + + if ( + is_string($value) + && preg_match('/^(0|[1-9]\d*)$/', $value) === 1 + ) { + $validated = filter_var($value, FILTER_VALIDATE_INT); + if ($validated !== false) { + return $validated; + } + } + + throw new \InvalidArgumentException('Expected an integer.'); + } + + private function normalizePanelUrl(string $url): string + { + if (trim($url) === '') { + return ''; + } + + try { + return PanelEndpointIdentity::canonicalUrl($url); + } catch (\InvalidArgumentException) { + return ''; + } + } +} diff --git a/Services/PterodactylInventoryService.php b/Services/PterodactylInventoryService.php new file mode 100644 index 0000000..31c7611 --- /dev/null +++ b/Services/PterodactylInventoryService.php @@ -0,0 +1,867 @@ +>|null + */ + private ?array $nodeSnapshot = null; + + /** + * The optional configuration argument keeps the production constructor + * container-friendly while allowing the HTTP contract to be tested without + * persisting extension settings. + * + * @param array{ + * pterodactyl_url?: string, + * pterodactyl_api_key?: string, + * exclusive_provisioning_control?: mixed + * }|null $config + */ + public function __construct(?array $config = null) + { + $config ??= $this->extensionConfig(); + $this->apiUrl = $this->normalizePanelUrl((string) ($config['pterodactyl_url'] ?? '')); + $this->apiKey = trim((string) ($config['pterodactyl_api_key'] ?? '')); + $this->exclusiveProvisioningControl = filter_var( + $config['exclusive_provisioning_control'] ?? false, + FILTER_VALIDATE_BOOLEAN + ); + + if ($this->apiUrl === '' || $this->apiKey === '') { + throw new \RuntimeException('Pterodactyl inventory credentials are not configured.'); + } + if (filter_var($this->apiUrl, FILTER_VALIDATE_URL) === false) { + throw new \RuntimeException('The Pterodactyl inventory URL is invalid.'); + } + } + + public function panelIdentity(): string + { + return PanelEndpointIdentity::hash($this->apiUrl); + } + + public function hasExclusiveProvisioningControl(): bool + { + return $this->exclusiveProvisioningControl; + } + + /** + * A seven-day local hold is a real guarantee only if every server create, + * move, resize, and allocation assignment on eligible nodes goes through + * this Paymenter deployment. This is an explicit operational contract; + * the Pterodactyl API cannot technically prevent a panel administrator. + */ + public function assertExclusiveProvisioningControl(): void + { + if (! $this->exclusiveProvisioningControl) { + throw new \RuntimeException( + 'Dynamic stock requires administrator-confirmed exclusive provisioning control ' + .'over every eligible Pterodactyl node.' + ); + } + } + + /** + * @return list + */ + public function locations(): array + { + return array_map(function (array $resource): array { + $attributes = $this->attributes($resource, 'location'); + + return [ + 'id' => $this->positiveInteger($attributes['id'] ?? null, 'location.id'), + 'short' => $this->stringValue($attributes['short'] ?? null, 'location.short'), + 'long' => $this->stringValue($attributes['long'] ?? null, 'location.long', true), + ]; + }, $this->paginated('/api/application/locations')); + } + + /** + * Pterodactyl 1.11 does not allow location_id as a NodeController filter. + * Read every page and apply the location constraint locally. + * + * @return list> + */ + public function nodesInLocation(int $locationId): array + { + if ($locationId <= 0) { + throw new \InvalidArgumentException('A positive Pterodactyl location ID is required.'); + } + + return array_values(array_filter( + $this->nodes(), + fn (array $node): bool => $node['location_id'] === $locationId + )); + } + + /** + * @return list> + */ + public function nodes(): array + { + if ($this->nodeSnapshot !== null) { + return $this->nodeSnapshot; + } + + $this->nodeSnapshot = array_map(function (array $resource): array { + $attributes = $this->attributes($resource, 'node'); + $allocated = $attributes['allocated_resources'] ?? null; + + if (! is_array($allocated)) { + throw new \RuntimeException( + 'Pterodactyl node inventory is missing allocated_resources. ' + .'Grant the application key node read permission and use Pterodactyl 1.11 or newer.' + ); + } + + return [ + 'id' => $this->positiveInteger($attributes['id'] ?? null, 'node.id'), + 'uuid' => $this->stringValue($attributes['uuid'] ?? null, 'node.uuid'), + 'name' => $this->stringValue($attributes['name'] ?? null, 'node.name'), + 'fqdn' => $this->stringValue($attributes['fqdn'] ?? null, 'node.fqdn'), + 'public' => $this->booleanValue($attributes['public'] ?? null, 'node.public'), + 'maintenance_mode' => $this->booleanValue( + $attributes['maintenance_mode'] ?? null, + 'node.maintenance_mode' + ), + 'location_id' => $this->positiveInteger( + $attributes['location_id'] ?? null, + 'node.location_id' + ), + 'memory' => $this->nonNegativeInteger($attributes['memory'] ?? null, 'node.memory'), + 'disk' => $this->nonNegativeInteger($attributes['disk'] ?? null, 'node.disk'), + 'memory_overallocate' => $this->integerValue( + $attributes['memory_overallocate'] ?? null, + 'node.memory_overallocate' + ), + 'disk_overallocate' => $this->integerValue( + $attributes['disk_overallocate'] ?? null, + 'node.disk_overallocate' + ), + 'allocated_resources' => [ + 'memory' => $this->nonNegativeInteger( + $allocated['memory'] ?? null, + 'node.allocated_resources.memory' + ), + 'disk' => $this->nonNegativeInteger( + $allocated['disk'] ?? null, + 'node.allocated_resources.disk' + ), + ], + 'available_allocations' => $this->availableNodeAllocations( + $resource + ), + ]; + }, $this->paginated( + '/api/application/nodes', + ['include' => 'allocations'] + )); + + return $this->nodeSnapshot; + } + + /** + * Server inventory is required for CPU accounting. A missing permission is + * an upstream error, never an implicit empty-server result. + * + * @param list $nodeIds + * @return array, + * allocation_headroom: int + * }>> + */ + public function serversForNodes(array $nodeIds): array + { + $nodeIds = array_values(array_unique(array_map('intval', $nodeIds))); + $grouped = array_fill_keys($nodeIds, []); + + if ($nodeIds === []) { + return []; + } + + foreach ($this->paginated( + '/api/application/servers', + ['include' => 'allocations'] + ) as $resource) { + $attributes = $this->attributes($resource, 'server'); + $nodeId = $this->positiveInteger($attributes['node'] ?? null, 'server.node'); + + if (! array_key_exists($nodeId, $grouped)) { + continue; + } + + $limits = $attributes['limits'] ?? null; + if (! is_array($limits)) { + throw new \RuntimeException('Pterodactyl server inventory is missing limits.'); + } + $featureLimits = $attributes['feature_limits'] ?? null; + if (! is_array($featureLimits)) { + throw new \RuntimeException( + 'Pterodactyl server inventory is missing feature_limits.' + ); + } + $allocationLimit = $this->nonNegativeInteger( + $featureLimits['allocations'] ?? null, + 'server.feature_limits.allocations' + ); + $allocationResources = $resource['relationships']['allocations']['data'] + ?? null; + if (! is_array($allocationResources) || ! array_is_list($allocationResources)) { + throw new \RuntimeException( + 'Pterodactyl server inventory is missing the allocations relationship. ' + .'Grant the application key allocation read permission.' + ); + } + $assignedAllocationIds = array_map(function (array $allocation): int { + $allocationAttributes = $this->attributes($allocation, 'allocation'); + + return $this->positiveInteger( + $allocationAttributes['id'] ?? null, + 'server.allocations.id' + ); + }, $allocationResources); + if ( + $assignedAllocationIds === [] + || count(array_unique($assignedAllocationIds)) + !== count($assignedAllocationIds) + || ! in_array( + $this->positiveInteger( + $attributes['allocation'] ?? null, + 'server.allocation' + ), + $assignedAllocationIds, + true + ) + ) { + throw new \RuntimeException( + 'Pterodactyl server allocation inventory is incomplete or inconsistent.' + ); + } + $externalId = $attributes['external_id'] ?? null; + if ( + $externalId !== null + && ( + ! is_string($externalId) + || trim($externalId) === '' + ) + ) { + throw new \RuntimeException( + 'Pterodactyl field server.external_id must be null or a non-empty string.' + ); + } + + $grouped[$nodeId][] = [ + 'id' => $this->positiveInteger($attributes['id'] ?? null, 'server.id'), + 'uuid' => $this->stringValue( + $attributes['uuid'] ?? null, + 'server.uuid' + ), + 'identifier' => $this->stringValue( + $attributes['identifier'] ?? null, + 'server.identifier' + ), + 'external_id' => $externalId === null + ? null + : trim($externalId), + 'node' => $nodeId, + 'memory' => $this->nonNegativeInteger( + $limits['memory'] ?? null, + 'server.limits.memory' + ), + 'cpu' => $this->nonNegativeInteger($limits['cpu'] ?? null, 'server.limits.cpu'), + 'disk' => $this->nonNegativeInteger( + $limits['disk'] ?? null, + 'server.limits.disk' + ), + 'allocation_limit' => $allocationLimit, + 'assigned_allocation_ids' => $assignedAllocationIds, + 'allocation_headroom' => max( + 0, + $allocationLimit - count($assignedAllocationIds) + ), + ]; + } + + return $grouped; + } + + /** + * @return list + */ + public function availableAllocationsForNode(int $nodeId): array + { + if ($this->nodeSnapshot !== null) { + $node = collect($this->nodeSnapshot)->firstWhere('id', $nodeId); + if (! is_array($node)) { + throw new \RuntimeException( + "Pterodactyl node {$nodeId} is absent from the inventory snapshot." + ); + } + + return $node['available_allocations']; + } + + $parsed = []; + foreach ($this->paginated("/api/application/nodes/{$nodeId}/allocations") as $resource) { + $attributes = $this->attributes($resource, 'allocation'); + $assigned = $this->booleanValue($attributes['assigned'] ?? null, 'allocation.assigned'); + $port = $this->positiveInteger( + $attributes['port'] ?? null, + 'allocation.port' + ); + if ($port > 65535) { + throw new \RuntimeException( + 'Pterodactyl field allocation.port must not exceed 65535.' + ); + } + + $parsed[] = [ + 'id' => $this->positiveInteger($attributes['id'] ?? null, 'allocation.id'), + 'ip' => $this->stringValue($attributes['ip'] ?? null, 'allocation.ip'), + 'port' => $port, + 'assigned' => $assigned, + ]; + } + $allocations = $this->availableAllocations($parsed); + + usort($allocations, fn (array $left, array $right): int => $left['id'] <=> $right['id']); + + return $allocations; + } + + /** + * Parse the NodeTransformer allocations include. A missing/null + * relationship means the API key lacks allocation permission and must fail + * stock closed rather than trigger per-node fallback requests. + * + * @return list + */ + private function availableNodeAllocations(array $nodeResource): array + { + $resources = $nodeResource['relationships']['allocations']['data'] + ?? null; + if (! is_array($resources) || ! array_is_list($resources)) { + throw new \RuntimeException( + 'Pterodactyl node inventory is missing the allocations relationship. ' + .'Grant the application key allocation read permission.' + ); + } + + $parsed = []; + foreach ($resources as $resource) { + $attributes = $this->attributes($resource, 'allocation'); + $assigned = $this->booleanValue( + $attributes['assigned'] ?? null, + 'allocation.assigned' + ); + + $port = $this->positiveInteger( + $attributes['port'] ?? null, + 'allocation.port' + ); + if ($port > 65535) { + throw new \RuntimeException( + 'Pterodactyl field allocation.port must not exceed 65535.' + ); + } + + $parsed[] = [ + 'id' => $this->positiveInteger( + $attributes['id'] ?? null, + 'allocation.id' + ), + 'ip' => $this->stringValue( + $attributes['ip'] ?? null, + 'allocation.ip' + ), + 'port' => $port, + 'assigned' => $assigned, + ]; + } + $allocations = $this->availableAllocations($parsed); + + usort( + $allocations, + fn (array $left, array $right): int => $left['id'] <=> $right['id'] + ); + + return $allocations; + } + + /** + * @param list $allocations + * @return list + */ + private function availableAllocations(array $allocations): array + { + $assignedIps = []; + foreach ($allocations as $allocation) { + if ($allocation['assigned']) { + $assignedIps[$this->canonicalIp($allocation['ip'])] = true; + } + } + + return array_values(array_map( + fn (array $allocation): array => [ + 'id' => $allocation['id'], + 'ip' => $allocation['ip'], + 'port' => $allocation['port'], + 'ip_in_use' => isset( + $assignedIps[$this->canonicalIp($allocation['ip'])] + ), + ], + array_filter( + $allocations, + fn (array $allocation): bool => ! $allocation['assigned'] + ) + )); + } + + private function canonicalIp(string $ip): string + { + $packed = @inet_pton(trim($ip)); + + return $packed === false + ? strtolower(trim($ip)) + : bin2hex($packed); + } + + /** + * Resolve the server identity used by Paymenter without scanning or + * trusting customer-provided node/resource data. + * + * @return array{ + * id: int, + * uuid: string, + * identifier: string, + * external_id: string, + * user_id: int, + * user_external_id: string, + * user_email: string, + * nest_id: int, + * egg_id: int, + * node: int, + * memory: int, + * cpu: int, + * disk: int, + * swap: int, + * io: int, + * threads: string|null, + * database_limit: int, + * allocation_limit: int, + * backup_limit: int, + * allocation: int, + * assigned_allocation_ids: list + * } + */ + public function serverByExternalId(int|string $externalId): array + { + $externalId = trim((string) $externalId); + if ($externalId === '') { + throw new \InvalidArgumentException('A Pterodactyl external server ID is required.'); + } + + $payload = $this->get( + '/api/application/servers/external/'.rawurlencode($externalId), + ['include' => 'allocations'] + ); + $attributes = $this->attributes($payload, 'server'); + $limits = $attributes['limits'] ?? null; + + if (! is_array($limits)) { + throw new \RuntimeException('Pterodactyl server inventory is missing limits.'); + } + $featureLimits = $attributes['feature_limits'] ?? null; + $threads = $limits['threads'] ?? null; + if ( + ! is_array($featureLimits) + || ($threads !== null && ! is_string($threads)) + ) { + throw new \RuntimeException( + 'Pterodactyl server inventory is missing build limits.' + ); + } + $primaryAllocation = $this->positiveInteger( + $attributes['allocation'] ?? null, + 'server.allocation' + ); + $allocationResources = $payload['relationships']['allocations']['data'] + ?? $attributes['relationships']['allocations']['data'] + ?? null; + if (! is_array($allocationResources) || ! array_is_list($allocationResources)) { + throw new \RuntimeException( + 'Pterodactyl server inventory is missing the allocations relationship.' + ); + } + $assignedAllocationIds = array_map(function (array $allocation): int { + $allocationAttributes = $this->attributes($allocation, 'allocation'); + + return $this->positiveInteger( + $allocationAttributes['id'] ?? null, + 'server.allocations.id' + ); + }, $allocationResources); + sort($assignedAllocationIds, SORT_NUMERIC); + if ( + $assignedAllocationIds === [] + || count(array_unique($assignedAllocationIds)) + !== count($assignedAllocationIds) + || ! in_array($primaryAllocation, $assignedAllocationIds, true) + ) { + throw new \RuntimeException( + 'Pterodactyl server allocation inventory is incomplete or inconsistent.' + ); + } + + $uuid = $this->stringValue( + $attributes['uuid'] ?? null, + 'server.uuid' + ); + if (! Str::isUuid($uuid)) { + throw new \RuntimeException( + 'Pterodactyl field server.uuid must be a valid UUID.' + ); + } + $serverExternalId = $this->stringValue( + $attributes['external_id'] ?? null, + 'server.external_id' + ); + $userId = $this->positiveInteger( + $attributes['user'] ?? null, + 'server.user' + ); + $userPayload = $this->get( + '/api/application/users/'.$userId, + [] + ); + $userAttributes = $this->attributes($userPayload, 'user'); + if ( + $this->positiveInteger( + $userAttributes['id'] ?? null, + 'user.id' + ) !== $userId + ) { + throw new \RuntimeException( + 'Pterodactyl returned a different server owner identity.' + ); + } + + return [ + 'id' => $this->positiveInteger($attributes['id'] ?? null, 'server.id'), + 'uuid' => $uuid, + 'identifier' => $this->stringValue( + $attributes['identifier'] ?? null, + 'server.identifier' + ), + 'external_id' => $serverExternalId, + 'user_id' => $userId, + 'user_external_id' => $this->stringValue( + $userAttributes['external_id'] ?? null, + 'user.external_id' + ), + 'user_email' => strtolower(trim($this->stringValue( + $userAttributes['email'] ?? null, + 'user.email' + ))), + 'nest_id' => $this->positiveInteger( + $attributes['nest'] ?? null, + 'server.nest' + ), + 'egg_id' => $this->positiveInteger( + $attributes['egg'] ?? null, + 'server.egg' + ), + 'node' => $this->positiveInteger($attributes['node'] ?? null, 'server.node'), + 'memory' => $this->nonNegativeInteger( + $limits['memory'] ?? null, + 'server.limits.memory' + ), + 'cpu' => $this->nonNegativeInteger($limits['cpu'] ?? null, 'server.limits.cpu'), + 'disk' => $this->nonNegativeInteger( + $limits['disk'] ?? null, + 'server.limits.disk' + ), + 'swap' => $this->nonNegativeInteger( + $limits['swap'] ?? null, + 'server.limits.swap' + ), + 'io' => $this->nonNegativeInteger( + $limits['io'] ?? null, + 'server.limits.io' + ), + 'threads' => $threads, + 'database_limit' => $this->nonNegativeInteger( + $featureLimits['databases'] ?? null, + 'server.feature_limits.databases' + ), + 'allocation_limit' => $this->nonNegativeInteger( + $featureLimits['allocations'] ?? null, + 'server.feature_limits.allocations' + ), + 'backup_limit' => $this->nonNegativeInteger( + $featureLimits['backups'] ?? null, + 'server.feature_limits.backups' + ), + 'allocation' => $primaryAllocation, + 'assigned_allocation_ids' => $assignedAllocationIds, + ]; + } + + public function testConnection(): array + { + try { + $nodes = $this->nodes(); + if ($nodes === []) { + throw new \RuntimeException( + 'Pterodactyl returned no nodes, so inventory permissions cannot be verified.' + ); + } + + $this->serversForNodes(array_column($nodes, 'id')); + $this->availableAllocationsForNode((int) $nodes[0]['id']); + + return [ + 'success' => true, + 'message' => 'Connection successful', + 'node_count' => count($nodes), + ]; + } catch (\Throwable $exception) { + return [ + 'success' => false, + 'message' => $exception->getMessage(), + ]; + } + } + + /** + * @return list> + */ + private function paginated(string $path, array $query = []): array + { + $page = 1; + $resources = []; + + while (true) { + $payload = $this->get($path, [ + ...$query, + 'page' => $page, + 'per_page' => 100, + ]); + $data = $payload['data'] ?? null; + + if (! is_array($data) || ! array_is_list($data)) { + throw new \RuntimeException('Pterodactyl returned an invalid paginated resource payload.'); + } + + $resources = array_merge($resources, $data); + $pagination = $payload['meta']['pagination'] ?? null; + + // Fractal includes pagination metadata. Accepting a missing block as + // one page also supports stock Pterodactyl's small relationship + // responses without silently skipping an advertised next page. + if ($pagination === null) { + break; + } + if (! is_array($pagination)) { + throw new \RuntimeException('Pterodactyl returned invalid pagination metadata.'); + } + + $currentPage = $this->positiveInteger( + $pagination['current_page'] ?? null, + 'pagination.current_page' + ); + $totalPages = $this->nonNegativeInteger( + $pagination['total_pages'] ?? null, + 'pagination.total_pages' + ); + + if ($totalPages === 0 || $currentPage >= $totalPages) { + break; + } + if ($currentPage < $page) { + throw new \RuntimeException('Pterodactyl pagination did not advance.'); + } + + $page = $currentPage + 1; + } + + return $resources; + } + + private function get(string $path, array $query): array + { + try { + $response = Http::withHeaders([ + 'Authorization' => 'Bearer '.$this->apiKey, + 'Accept' => 'application/json', + ]) + ->timeout(3) + ->connectTimeout(2) + ->retry( + 2, + 250, + fn ($exception): bool => $exception instanceof ConnectionException, + throw: false + ) + ->get($this->apiUrl.$path, $query); + } catch (ConnectionException $exception) { + \report($exception); + + throw new \RuntimeException('Pterodactyl API connection failed.', previous: $exception); + } + + if ($response->status() === 429) { + throw new \RuntimeException('Pterodactyl rate limit exceeded. Retry in a few seconds.'); + } + + if ($response->failed()) { + \report(new \RuntimeException(sprintf( + 'Pterodactyl inventory API error (%d) body: %s', + $response->status(), + $response->body() + ))); + + throw new \RuntimeException(sprintf( + 'Pterodactyl inventory API error (%d). Verify the application API key permissions.', + $response->status() + )); + } + + $payload = $response->json(); + if (! is_array($payload)) { + throw new \RuntimeException('Pterodactyl returned invalid JSON inventory data.'); + } + + return $payload; + } + + private function attributes(array $resource, string $expectedObject): array + { + $object = $resource['object'] ?? null; + $attributes = $resource['attributes'] ?? null; + + if ($object !== $expectedObject || ! is_array($attributes)) { + throw new \RuntimeException("Pterodactyl returned an invalid {$expectedObject} resource."); + } + + return $attributes; + } + + private function positiveInteger(mixed $value, string $field): int + { + $value = $this->integerValue($value, $field); + + if ($value <= 0) { + throw new \RuntimeException("Pterodactyl field {$field} must be positive."); + } + + return $value; + } + + private function nonNegativeInteger(mixed $value, string $field): int + { + $value = $this->integerValue($value, $field); + + if ($value < 0) { + throw new \RuntimeException("Pterodactyl field {$field} must not be negative."); + } + + return $value; + } + + private function integerValue(mixed $value, string $field): int + { + if (! is_int($value) && ! ( + is_string($value) + && preg_match('/^-?(0|[1-9]\d*)$/', $value) === 1 + )) { + throw new \RuntimeException("Pterodactyl field {$field} must be an integer."); + } + + $validated = filter_var($value, FILTER_VALIDATE_INT); + if ($validated === false) { + throw new \RuntimeException( + "Pterodactyl field {$field} is outside the supported integer range." + ); + } + + return $validated; + } + + private function booleanValue(mixed $value, string $field): bool + { + if (! is_bool($value)) { + throw new \RuntimeException("Pterodactyl field {$field} must be a boolean."); + } + + return $value; + } + + private function stringValue(mixed $value, string $field, bool $allowEmpty = false): string + { + if (! is_string($value) || (! $allowEmpty && trim($value) === '')) { + throw new \RuntimeException("Pterodactyl field {$field} must be a string."); + } + + return $value; + } + + private function normalizePanelUrl(string $url): string + { + if (trim($url) === '') { + return ''; + } + + try { + return PanelEndpointIdentity::canonicalUrl($url); + } catch (\InvalidArgumentException $exception) { + throw new \RuntimeException( + 'The Pterodactyl inventory URL is invalid.', + previous: $exception + ); + } + } + + /** + * @return array + */ + private function extensionConfig(): array + { + return Extension::query() + ->where('extension', 'DynamicPterodactyl') + ->where('enabled', true) + ->first() + ?->settings + ->pluck('value', 'key') + ->toArray() ?? []; + } +} diff --git a/Services/ReservationConfigurationService.php b/Services/ReservationConfigurationService.php index 2649152..99d2d36 100644 --- a/Services/ReservationConfigurationService.php +++ b/Services/ReservationConfigurationService.php @@ -9,6 +9,11 @@ use App\Models\Extension; use App\Models\Product; use App\Models\Service; +use App\Models\User; +use App\Support\PanelEndpointIdentity; +use App\Support\StrictInteger; +use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidResourceSelectionException; +use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException; class ReservationConfigurationService { @@ -28,10 +33,16 @@ class ReservationConfigurationService * currency_code: string, * location_id: int, * resources: array{memory: int, cpu: int, disk: int}, - * calculated_price: float, + * calculated_price: string, * pricing_version: string, * formula_version: string, - * config_options: array> + * config_options: array>, + * allocation_requirements: array{ + * required_count: int, + * mappings: array>, + * allowed_port_ranges: array, + * dedicated_ip: bool + * } * } */ public function forCartItem(CartItem $cartItem): array @@ -51,11 +62,18 @@ public function forCartItem(CartItem $cartItem): array throw new DisplayException('Dynamic resource products currently require a quantity of one.'); } + try { + $stockConfiguration = app(ProductResourceConfigurationService::class) + ->forQuote($cartItem->product, (array) ($cartItem->config_options ?? [])); + } catch (InvalidResourceSelectionException|InvalidStockConfigurationException $exception) { + throw new DisplayException($exception->getMessage(), previous: $exception); + } + $selectedOptions = collect($cartItem->config_options ?? []) ->keyBy(fn ($option) => (int) data_get($option, 'option_id')); - $resources = []; - $locationId = null; + $resources = $stockConfiguration['resources']; + $locationId = (int) $stockConfiguration['location_id']; $configurationOptions = []; foreach ($cartItem->product->configOptions as $option) { @@ -65,16 +83,11 @@ public function forCartItem(CartItem $cartItem): array $environmentKey = strtolower((string) ($option->env_variable ?: $option->name)); if ($option->type === 'dynamic_slider' && in_array($resourceType, ['memory', 'cpu', 'disk'], true)) { - $minimum = $resourceType === 'cpu' ? 0 : 1; - if ($value === null || ! is_numeric($value) || (float) $value < $minimum) { - throw new DisplayException("A valid {$resourceType} selection is required."); - } - - $resources[$resourceType] = (int) $value; + $value = $resources[$resourceType]; } if ($environmentKey === 'location' || strtolower($option->name) === 'location') { - $locationId = $this->resolveLocationId($option, $value); + $value = (int) $value; } $configurationOptions[] = [ @@ -87,26 +100,24 @@ public function forCartItem(CartItem $cartItem): array ]; } - $staticResources = $this->resolveStaticResources($cartItem); - foreach (['memory', 'cpu', 'disk'] as $requiredResource) { - if (! array_key_exists($requiredResource, $resources)) { - $resources[$requiredResource] = $staticResources[$requiredResource] - ?? throw new DisplayException( - "The {$requiredResource} resource is missing from both the slider and product settings." - ); - } - } - - $locationId ??= $this->resolveStaticLocationId($cartItem); - if ($locationId === null || $locationId <= 0) { - throw new DisplayException('A deployment location is required before this product can be reserved.'); - } - usort($configurationOptions, fn (array $left, array $right) => $left['id'] <=> $right['id']); - $calculatedPrice = round((float) $cartItem->price->total * (int) $cartItem->quantity, 2); + $calculatedPrice = $this->canonicalMoney( + $cartItem->price->total, + (int) $cartItem->quantity + ); $currencyCode = strtoupper((string) $cartItem->cart->currency_code); $panel = $this->checkoutPanelIdentity($cartItem); + $allocationRequirements = [ + 'required_count' => (int) $stockConfiguration['allocation_count'], + 'mappings' => (array) $stockConfiguration['allocation_mappings'], + 'allowed_port_ranges' => (array) ( + $stockConfiguration['allowed_port_ranges'] ?? [] + ), + 'dedicated_ip' => (bool) ( + $stockConfiguration['dedicated_ip'] ?? false + ), + ]; $pricingIdentity = [ 'product_id' => (int) $cartItem->product_id, 'plan_id' => (int) $cartItem->plan_id, @@ -114,11 +125,16 @@ public function forCartItem(CartItem $cartItem): array 'calculated_price' => $calculatedPrice, 'config_options' => $configurationOptions, ]; + $customerId = $cartItem->cart->user_id !== null + ? (int) $cartItem->cart->user_id + : (auth()->id() !== null ? (int) auth()->id() : null); + $provisioningIdentity = $this->provisioningIdentity( + $cartItem->product, + $customerId + ); return [ - 'customer_id' => $cartItem->cart->user_id !== null - ? (int) $cartItem->cart->user_id - : (auth()->id() !== null ? (int) auth()->id() : null), + 'customer_id' => $customerId, 'cart_id' => (int) $cartItem->cart_id, 'server_extension_id' => $panel['server_extension_id'], 'panel_identity' => $panel['panel_identity'], @@ -132,6 +148,8 @@ public function forCartItem(CartItem $cartItem): array 'pricing_version' => hash('sha256', $this->canonicalJson($pricingIdentity)), 'formula_version' => self::FORMULA_VERSION, 'config_options' => $configurationOptions, + 'allocation_requirements' => $allocationRequirements, + 'provisioning_identity' => $provisioningIdentity, ]; } @@ -149,6 +167,7 @@ public function requiresReservation(int $productId): bool return ConfigOption::query() ->whereHas('products', fn ($query) => $query->whereKey($productId)) ->where('type', 'dynamic_slider') + ->where('hidden', false) ->whereNull('parent_id') ->get() ->contains(fn (ConfigOption $option) => in_array( @@ -158,6 +177,24 @@ public function requiresReservation(int $productId): bool )); } + /** + * A seven-day capacity claim is truthful only when every server create, + * move, resize, and allocation assignment on eligible nodes participates + * in this protocol. + */ + public function assertExclusiveProvisioningControl(): void + { + try { + app(PterodactylInventoryService::class) + ->assertExclusiveProvisioningControl(); + } catch (\RuntimeException $exception) { + throw new DisplayException( + 'Dynamic ordering is disabled until an administrator confirms that this Paymenter instance exclusively controls all provisioning on eligible Pterodactyl nodes.', + previous: $exception + ); + } + } + /** * @param array $snapshot * @return array @@ -180,9 +217,40 @@ public function withNode(array $snapshot, int $nodeId): array 'pricing_version' => $snapshot['pricing_version'], 'formula_version' => $snapshot['formula_version'], 'config_options' => $snapshot['config_options'], + 'allocation_requirements' => $snapshot['allocation_requirements'], + 'provisioning_identity' => $snapshot['provisioning_identity'], ]); } + /** + * Add the exact Pterodactyl placement selected under the capacity lock. + * + * @param array $snapshot + * @param array> $allocations + * @return array + */ + public function withPlacement(array $snapshot, int $nodeId, array $allocations): array + { + $payload = $this->withNode($snapshot, $nodeId); + $payload['allocations'] = array_values(array_map( + fn (array $allocation) => [ + 'allocation_id' => (int) ($allocation['allocation_id'] ?? $allocation['id'] ?? 0), + 'ip' => (string) ($allocation['ip'] ?? ''), + 'port' => (int) ($allocation['port'] ?? 0), + 'environment_key' => $allocation['environment_key'] ?? null, + 'is_primary' => (bool) ($allocation['is_primary'] ?? false), + ], + $allocations + )); + + usort( + $payload['allocations'], + fn (array $left, array $right) => $left['allocation_id'] <=> $right['allocation_id'] + ); + + return $this->canonicalize($payload); + } + /** * Transfer a guest payload to its authenticated customer without changing * any pricing, placement, or resource input. @@ -190,9 +258,17 @@ public function withNode(array $snapshot, int $nodeId): array * @param array $payload * @return array */ - public function withCustomer(array $payload, int $customerId): array + public function withCustomer( + array $payload, + int $customerId, + string $customerEmail + ): array { $payload['customer_id'] = $customerId; + $payload['provisioning_identity']['user_external_id'] + = $this->pterodactylUserExternalId($customerId); + $payload['provisioning_identity']['user_email'] + = $this->normalizeCustomerEmail($customerEmail); return $this->canonicalize($payload); } @@ -205,14 +281,67 @@ public function fingerprint(array $payload): string return hash('sha256', $this->canonicalJson($payload)); } + private function canonicalMoney(mixed $unitPrice, int $quantity): string + { + if ( + $quantity !== 1 + || ! is_string($unitPrice) + || preg_match('/^(0|[1-9]\d*)\.(\d{2})$/D', $unitPrice) !== 1 + ) { + throw new DisplayException( + 'The dynamic product price is outside the supported invoice format.' + ); + } + + $wholeDigits = strlen(strstr($unitPrice, '.', true)); + if ($wholeDigits > 15) { + throw new DisplayException( + 'The dynamic product price exceeds the supported invoice range.' + ); + } + + return $unitPrice; + } + /** - * Prove that the service still represents the immutable checkout payload. + * Prove that the service still owns the immutable checkout payload. + * + * Product defaults, config-option metadata, and server settings are + * intentionally not recomputed here: administrators may edit them while a + * seven-day quote is open. The signed reservation remains authoritative + * and the provisioner overrides placement and resources from that snapshot. * * @param object $reservation */ public function assertServiceMatches(Service $service, object $reservation): void { - $expected = [ + try { + $payload = json_decode( + (string) $reservation->configuration_payload, + true, + 512, + JSON_THROW_ON_ERROR + ); + } catch (\JsonException $exception) { + throw new \RuntimeException( + 'The capacity reservation snapshot is unreadable.', + previous: $exception + ); + } + if ( + ! is_array($payload) + || ! hash_equals( + (string) $reservation->configuration_fingerprint, + $this->fingerprint($payload) + ) + ) { + throw new \RuntimeException( + 'The capacity reservation snapshot failed its integrity check.' + ); + } + + $reservationIdentity = [ + 'customer_id' => (int) $reservation->user_id, 'server_extension_id' => (int) $reservation->server_extension_id, 'panel_identity' => (string) $reservation->panel_identity, 'product_id' => (int) $reservation->product_id, @@ -224,37 +353,137 @@ public function assertServiceMatches(Service $service, object $reservation): voi 'cpu' => (int) $reservation->cpu, 'disk' => (int) $reservation->disk, 'location' => (int) $reservation->location_id, + 'node_id' => (int) $reservation->node_id, ]; - - $properties = collect(ExtensionHelper::getServiceProperties($service)) - ->mapWithKeys(fn ($value, $key) => [strtolower((string) $key) => $value]); - $settings = $service->product->settings() - ->get(['key', 'value']) - ->mapWithKeys(fn ($setting) => [strtolower((string) $setting->key) => $setting->value]); - $server = $service->product->server; - $serverSettings = $server?->settings - ?->pluck('value', 'key') ?? collect(); - - $actual = [ - 'server_extension_id' => (int) $service->product->server_id, - 'panel_identity' => hash( - 'sha256', - $this->normalizePanelUrl((string) $serverSettings->get('host')) - ), + $payloadIdentity = [ + 'customer_id' => (int) ($payload['customer_id'] ?? 0), + 'server_extension_id' => (int) ($payload['server_extension_id'] ?? 0), + 'panel_identity' => (string) ($payload['panel_identity'] ?? ''), + 'product_id' => (int) ($payload['product_id'] ?? 0), + 'plan_id' => (int) ($payload['plan_id'] ?? 0), + 'quantity' => (int) ($payload['quantity'] ?? 0), + 'currency_code' => strtoupper((string) ($payload['currency_code'] ?? '')), + 'user_id' => (int) ($payload['customer_id'] ?? 0), + 'memory' => (int) data_get($payload, 'resources.memory', 0), + 'cpu' => (int) data_get($payload, 'resources.cpu', 0), + 'disk' => (int) data_get($payload, 'resources.disk', 0), + 'location' => (int) ($payload['location_id'] ?? 0), + 'node_id' => (int) ($payload['node_id'] ?? 0), + ]; + $serviceIdentity = [ + 'service_id' => (int) $service->id, 'product_id' => (int) $service->product_id, 'plan_id' => (int) $service->plan_id, 'quantity' => (int) $service->quantity, 'currency_code' => strtoupper((string) $service->currency_code), 'user_id' => (int) $service->user_id, - 'memory' => (int) ($properties->get('memory') ?? $settings->get('memory')), - 'cpu' => (int) ($properties->get('cpu') ?? $settings->get('cpu')), - 'disk' => (int) ($properties->get('disk') ?? $settings->get('disk')), - 'location' => $this->serviceLocationId($service, $properties->get('location')), ]; + $expectedServiceIdentity = [ + 'service_id' => (int) $reservation->service_id, + 'product_id' => (int) $reservation->product_id, + 'plan_id' => (int) $reservation->plan_id, + 'quantity' => (int) $reservation->quantity, + 'currency_code' => strtoupper((string) $reservation->currency_code), + 'user_id' => (int) $reservation->user_id, + ]; + + if ( + $reservationIdentity !== $payloadIdentity + || $serviceIdentity !== $expectedServiceIdentity + ) { + throw new \RuntimeException( + 'The service identity does not match its immutable capacity reservation.' + ); + } + + $provisioningIdentity = (array) ( + $payload['provisioning_identity'] ?? [] + ); + if ( + StrictInteger::parse($provisioningIdentity['nest_id'] ?? null) === null + || (int) $provisioningIdentity['nest_id'] <= 0 + || StrictInteger::parse($provisioningIdentity['egg_id'] ?? null) === null + || (int) $provisioningIdentity['egg_id'] <= 0 + || ! hash_equals( + $this->pterodactylUserExternalId((int) $service->user_id), + (string) ($provisioningIdentity['user_external_id'] ?? '') + ) + || strtolower(trim((string) ( + $provisioningIdentity['user_email'] ?? '' + ))) === '' + ) { + throw new \RuntimeException( + 'The provisioning identity does not match its immutable capacity reservation.' + ); + } + } + + /** + * @return array{ + * nest_id: int, + * egg_id: int, + * user_external_id: string|null, + * user_email: string|null + * } + */ + private function provisioningIdentity( + Product $product, + ?int $customerId + ): array { + $settings = ExtensionHelper::settingsToArray($product->settings); + $nestId = StrictInteger::parse($settings['nest_id'] ?? null); + $eggId = StrictInteger::parse($settings['egg_id'] ?? null); + if ( + $nestId === null + || $nestId <= 0 + || $eggId === null + || $eggId <= 0 + ) { + throw new DisplayException( + 'The dynamic product must have one valid Pterodactyl nest and egg.' + ); + } + + return [ + 'nest_id' => $nestId, + 'egg_id' => $eggId, + 'user_external_id' => $customerId === null + ? null + : $this->pterodactylUserExternalId($customerId), + 'user_email' => $customerId === null + ? null + : $this->paymenterUserEmail($customerId), + ]; + } + + private function pterodactylUserExternalId(int $customerId): string + { + if ($customerId <= 0) { + throw new \InvalidArgumentException( + 'A valid Paymenter customer is required for provisioning.' + ); + } + + return "paymenter-user-{$customerId}"; + } - if ($expected !== $actual) { - throw new \RuntimeException('The service configuration does not match its capacity reservation.'); + private function paymenterUserEmail(int $customerId): string + { + return $this->normalizeCustomerEmail((string) User::query() + ->whereKey($customerId) + ->value('email')); + } + + private function normalizeCustomerEmail(string $email): string + { + $email = strtolower(trim($email)); + if ($email === '') { + throw new \InvalidArgumentException( + 'A valid Paymenter customer email is required for provisioning.' + ); } + + return $email; } /** @@ -294,82 +523,15 @@ private function checkoutPanelIdentity(CartItem $cartItem): array private function normalizePanelUrl(string $url): string { - return strtolower(rtrim(trim($url), '/')); - } - - private function resolveLocationId(ConfigOption $option, mixed $value): ?int - { - if ($value === null || $value === '') { - return null; + if (trim($url) === '') { + return ''; } - if ($option->type === 'dynamic_slider') { - return is_numeric($value) ? (int) $value : null; + try { + return PanelEndpointIdentity::canonicalUrl($url); + } catch (\InvalidArgumentException) { + return ''; } - - $selectedChild = $option->children->firstWhere('id', (int) $value); - $resolved = $selectedChild?->env_variable ?? $value; - - return is_numeric($resolved) ? (int) $resolved : null; - } - - private function resolveStaticLocationId(CartItem $cartItem): ?int - { - $settings = $cartItem->product->settings()->pluck('value', 'key'); - $locations = $settings->get('location_ids'); - - if (is_string($locations)) { - $decoded = json_decode($locations, true); - $locations = json_last_error() === JSON_ERROR_NONE ? $decoded : $locations; - } - - $locations = is_array($locations) ? array_values($locations) : [$locations]; - $locations = array_values(array_filter($locations, fn ($location) => is_numeric($location))); - - return count($locations) === 1 ? (int) $locations[0] : null; - } - - /** - * Static Pterodactyl limits fill resources whose sliders are intentionally - * disabled. They become part of the same immutable payload. - * - * @return array{memory?: int, cpu?: int, disk?: int} - */ - private function resolveStaticResources(CartItem $cartItem): array - { - $settings = $cartItem->product->settings() - ->get(['key', 'value']) - ->mapWithKeys(fn ($setting) => [strtolower((string) $setting->key) => $setting->value]); - $resources = []; - - foreach (['memory', 'cpu', 'disk'] as $resourceType) { - $value = $settings->get($resourceType); - $minimum = $resourceType === 'cpu' ? 0 : 1; - - if (is_numeric($value) && (float) $value >= $minimum) { - $resources[$resourceType] = (int) $value; - } - } - - return $resources; - } - - private function serviceLocationId(Service $service, mixed $propertyLocation): int - { - if (is_numeric($propertyLocation)) { - return (int) $propertyLocation; - } - - $locations = $service->product->settings()->where('key', 'location_ids')->value('value'); - if (is_string($locations)) { - $decoded = json_decode($locations, true); - $locations = json_last_error() === JSON_ERROR_NONE ? $decoded : $locations; - } - - $locations = is_array($locations) ? array_values($locations) : [$locations]; - $locations = array_values(array_filter($locations, fn ($location) => is_numeric($location))); - - return count($locations) === 1 ? (int) $locations[0] : 0; } /** diff --git a/Services/ReservationService.php b/Services/ReservationService.php index 646b943..6a7e8c4 100644 --- a/Services/ReservationService.php +++ b/Services/ReservationService.php @@ -3,15 +3,25 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Services; use App\Exceptions\DisplayException; +use App\Exceptions\PermanentProvisioningException; use App\Models\CartItem; use App\Models\Extension; +use App\Models\Invoice; use App\Models\Service; use App\Models\User; +use App\Services\Invoice\CancelInvoiceService; +use App\Services\Invoice\CapacityInvoicePaymentService; +use App\Services\Service\CapacityConfigurationLockService; +use App\Services\Service\FulfillmentStatusTransitionService; +use App\Services\Service\ProductStockService; +use App\Support\StrictInteger; use Carbon\Carbon; use Carbon\CarbonInterface; +use Illuminate\Database\Query\Builder; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Gate; use Illuminate\Support\Str; +use Paymenter\Extensions\Others\DynamicPterodactyl\Models\ReservationAllocation; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\ResourceReservation; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\Concerns\AuditsExtensionActions; @@ -21,6 +31,8 @@ class ReservationService private const PROVISIONING_LEASE_MINUTES = 5; + private const RETRY_DELAYS_SECONDS = [15, 60, 300, 900, 1800, 3600, 10800]; + private NodeSelectionService $nodeService; private ReservationConfigurationService $configurationService; @@ -52,21 +64,103 @@ public function __construct( */ public function reserveForCartItem(CartItem $cartItem): array { - $snapshot = $this->configurationService->forCartItem($cartItem); - $ownerId = $snapshot['customer_id']; - - return DB::transaction(function () use ($cartItem, $snapshot, $ownerId) { - DB::table('ptero_resource_reservations') - ->where('location_id', $snapshot['location_id']) - ->where('status', 'pending') + return DB::transaction(function () use ($cartItem) { + // Product is the shared first lock for configuration readers and + // writers. Build the snapshot only after the complete + // Product→option→plan→price lock set is held, then retain those + // locks until the capacity hold has been inserted. + $product = app(CapacityConfigurationLockService::class) + ->lockProduct((int) $cartItem->product_id); + $cartItem = CartItem::query() + ->whereKey($cartItem->id) ->lockForUpdate() - ->get(); + ->firstOrFail(); + if ((int) $cartItem->product_id !== (int) $product->id) { + throw new \RuntimeException( + 'The cart product changed while its capacity configuration was being locked.' + ); + } + $plan = $product->plans->firstWhere( + 'id', + (int) $cartItem->plan_id + ); + if ($plan === null) { + throw new DisplayException( + 'The selected product plan is no longer available.' + ); + } + $cartItem->setRelation('product', $product); + $cartItem->setRelation('plan', $plan); + $cartItem->loadMissing('cart'); + + $snapshot = $this->configurationService + ->forCartItem($cartItem); + $ownerId = $snapshot['customer_id']; + $previousScope = DB::table('ptero_resource_reservations') + ->where('cart_item_id', $cartItem->id) + ->where('status', ResourceReservation::STATUS_PENDING) + ->first(['panel_identity', 'location_id']); + $scopes = collect([ + [ + 'panel_identity' => (string) $snapshot['panel_identity'], + 'location_id' => (int) $snapshot['location_id'], + ], + $previousScope !== null && $previousScope->panel_identity !== null + ? [ + 'panel_identity' => (string) $previousScope->panel_identity, + 'location_id' => (int) $previousScope->location_id, + ] + : null, + ]) + ->filter() + ->unique(fn (array $scope) => $this->capacityScopeKey($scope)) + ->sortBy(fn (array $scope) => $this->capacityScopeKey($scope)) + ->values(); + + foreach ($scopes as $scope) { + DB::table('ptero_capacity_scopes')->insertOrIgnore([ + ...$scope, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + foreach ($scopes as $scope) { + DB::table('ptero_capacity_scopes') + ->where('panel_identity', $scope['panel_identity']) + ->where('location_id', $scope['location_id']) + ->lockForUpdate() + ->first(); + } + foreach ($scopes as $scope) { + DB::table('ptero_resource_reservations') + ->where('panel_identity', $scope['panel_identity']) + ->where('location_id', $scope['location_id']) + ->where(function (Builder $query) { + $this->applyCapacityHoldingScope($query); + }) + ->lockForUpdate() + ->get(); + } $existing = DB::table('ptero_resource_reservations') ->where('cart_item_id', $cartItem->id) ->where('status', 'pending') ->lockForUpdate() ->first(); + if ( + $existing !== null + && ! $scopes->contains( + fn (array $scope) => $this->capacityScopeKey($scope) + === $this->capacityScopeKey([ + 'panel_identity' => (string) $existing->panel_identity, + 'location_id' => (int) $existing->location_id, + ]) + ) + ) { + throw new \RuntimeException( + 'The capacity scope changed concurrently; retry the cart update.' + ); + } if ($existing !== null && $existing->user_id !== null && (int) $existing->user_id !== (int) $ownerId) { throw new DisplayException('This cart capacity hold belongs to a different customer.'); @@ -79,6 +173,7 @@ public function reserveForCartItem(CartItem $cartItem): array 'status' => 'expired', 'updated_at' => now(), ]); + $this->releaseAllocationClaims((int) $existing->id); $existing = null; } @@ -90,6 +185,7 @@ public function reserveForCartItem(CartItem $cartItem): array ->update([ 'user_id' => $ownerId, 'expires_at' => $expiresAt, + 'guaranteed_until' => $expiresAt, 'updated_at' => now(), ]); @@ -110,19 +206,67 @@ public function reserveForCartItem(CartItem $cartItem): array 'admin_notes' => 'Replaced after cart configuration changed.', 'updated_at' => now(), ]); + $this->releaseAllocationClaims((int) $existing->id); } - $node = $this->nodeService->selectBestNode( - $snapshot['location_id'], - $snapshot['resources'], - $excludedToken + $requiredAllocations = max( + 1, + (int) data_get($snapshot, 'allocation_requirements.required_count', 1) ); + $requiredPorts = collect( + data_get($snapshot, 'allocation_requirements.mappings', []) + ) + ->pluck('requested_port') + ->filter(fn ($port) => $port !== null) + ->map(fn ($port) => (int) $port) + ->values() + ->all(); + $node = method_exists($this->nodeService, 'selectBestNodeWithAllocations') + ? $this->nodeService->selectBestNodeWithAllocations( + $snapshot['location_id'], + $snapshot['resources'], + $requiredAllocations, + $excludedToken, + $requiredPorts, + (array) data_get( + $snapshot, + 'allocation_requirements.allowed_port_ranges', + [] + ), + (bool) data_get( + $snapshot, + 'allocation_requirements.dedicated_ip', + false + ) + ) + : $this->nodeService->selectBestNode( + $snapshot['location_id'], + $snapshot['resources'], + $excludedToken + ); if ($node === null) { throw new DisplayException('No node has enough capacity for this configuration.'); } - $payload = $this->configurationService->withNode($snapshot, (int) $node['node_id']); + $availableAllocations = array_values( + $node['selected_allocations'] ?? $node['available_allocations'] ?? [] + ); + if (count($availableAllocations) < $requiredAllocations) { + throw new DisplayException( + 'No node has enough unassigned allocations for this configuration.' + ); + } + + $selectedAllocations = $this->mapAllocationRequirements( + $availableAllocations, + (array) data_get($snapshot, 'allocation_requirements.mappings', []) + ); + $payload = $this->configurationService->withPlacement( + $snapshot, + (int) $node['node_id'], + $selectedAllocations + ); $fingerprint = $this->configurationService->fingerprint($payload); $token = Str::random(64); $expiresAt = now()->addMinutes($this->ttlMinutes); @@ -154,10 +298,24 @@ public function reserveForCartItem(CartItem $cartItem): array 'pricing_breakdown' => json_encode([], JSON_THROW_ON_ERROR), 'status' => 'pending', 'expires_at' => $expiresAt, + 'guaranteed_until' => $expiresAt, 'created_at' => now(), 'updated_at' => now(), ]); + foreach ($selectedAllocations as $allocation) { + ReservationAllocation::query()->create([ + 'reservation_id' => $id, + 'panel_identity' => $snapshot['panel_identity'], + 'node_id' => (int) $node['node_id'], + 'allocation_id' => (int) $allocation['allocation_id'], + 'ip' => $allocation['ip'] ?: null, + 'port' => (int) $allocation['port'], + 'environment_key' => $allocation['environment_key'], + 'is_primary' => (bool) $allocation['is_primary'], + ]); + } + $this->safeAudit('created', 'reservation', $id, [ 'reservation_id' => $id, 'configuration_fingerprint' => $fingerprint, @@ -186,6 +344,10 @@ public function reserveForCartItem(CartItem $cartItem): array public function transferCartOwnership(int $cartId, int $userId): int { return DB::transaction(function () use ($cartId, $userId) { + $user = User::query() + ->whereKey($userId) + ->lockForUpdate() + ->firstOrFail(); $reservations = DB::table('ptero_resource_reservations') ->where('cart_id', $cartId) ->where('status', 'pending') @@ -211,7 +373,11 @@ public function transferCartOwnership(int $cartId, int $userId): int throw new \RuntimeException('Capacity hold payload does not match its cart.'); } - $payload = $this->configurationService->withCustomer($payload, $userId); + $payload = $this->configurationService->withCustomer( + $payload, + $userId, + (string) $user->email + ); DB::table('ptero_resource_reservations') ->where('id', $reservation->id) @@ -234,16 +400,35 @@ public function bindCartItemToService( CartItem $cartItem, Service $service, User $user, - CarbonInterface $holdUntil + CarbonInterface $holdUntil, + ?Invoice $invoice = null ): void { $snapshot = $this->configurationService->forCartItem($cartItem); - DB::transaction(function () use ($cartItem, $service, $user, $holdUntil, $snapshot) { + DB::transaction(function () use ($cartItem, $service, $user, $holdUntil, $invoice, $snapshot) { + $lockedInvoice = null; + if ($invoice !== null) { + $lockedInvoice = Invoice::query() + ->whereKey($invoice->id) + ->lockForUpdate() + ->firstOrFail(); + } + $lockedService = Service::query() + ->whereKey($service->id) + ->lockForUpdate() + ->firstOrFail(); $reservation = DB::table('ptero_resource_reservations') ->where('cart_item_id', $cartItem->id) ->where('status', 'pending') ->lockForUpdate() ->first(); + $invoiceItems = $lockedInvoice === null + ? collect() + : DB::table('invoice_items') + ->where('invoice_id', $lockedInvoice->id) + ->orderBy('id') + ->lockForUpdate() + ->get(); if ($reservation === null || Carbon::parse($reservation->expires_at)->isPast()) { throw new DisplayException('Capacity hold expired during checkout. Please reconfigure this product.'); @@ -253,7 +438,7 @@ public function bindCartItemToService( throw new DisplayException('This capacity hold belongs to a different customer.'); } - if ($reservation->service_id !== null && (int) $reservation->service_id !== (int) $service->id) { + if ($reservation->service_id !== null && (int) $reservation->service_id !== (int) $lockedService->id) { throw new \RuntimeException('This capacity hold is already bound to another service.'); } @@ -262,31 +447,326 @@ public function bindCartItemToService( } if ( - (int) $service->product_id !== (int) $reservation->product_id - || (int) $service->plan_id !== (int) $reservation->plan_id - || (int) $service->quantity !== (int) $reservation->quantity - || strtoupper((string) $service->currency_code) !== strtoupper((string) $reservation->currency_code) + (int) $lockedService->product_id !== (int) $reservation->product_id + || (int) $lockedService->plan_id !== (int) $reservation->plan_id + || (int) $lockedService->quantity !== (int) $reservation->quantity + || strtoupper((string) $lockedService->currency_code) !== strtoupper((string) $reservation->currency_code) ) { throw new \RuntimeException('The new service does not match its capacity reservation.'); } + if ( + $lockedInvoice !== null + && ( + $lockedInvoice->status !== Invoice::STATUS_PENDING + || (int) $lockedInvoice->user_id !== (int) $user->id + || strtoupper((string) $lockedInvoice->currency_code) + !== strtoupper((string) $lockedService->currency_code) + ) + ) { + throw new \RuntimeException( + 'The checkout invoice does not match its capacity-backed service.' + ); + } + if ( + $lockedInvoice !== null + && ! $invoiceItems->contains( + fn ($item): bool => + (int) $item->reference_id === (int) $lockedService->id + && (string) $item->reference_type === $lockedService->getMorphClass() + && (int) $item->quantity === (int) $lockedService->quantity + ) + ) { + throw new \RuntimeException( + 'The checkout invoice is missing the immutable capacity-backed service line.' + ); + } DB::table('ptero_resource_reservations') ->where('id', $reservation->id) ->update([ - 'service_id' => $service->id, + 'service_id' => $lockedService->id, + 'service_guard_id' => $lockedService->id, + 'invoice_id' => $lockedInvoice?->id, 'user_id' => $user->id, 'expires_at' => $holdUntil, + 'guaranteed_until' => $holdUntil, 'updated_at' => now(), ]); $this->safeAudit('reservation_bound', 'resource_reservation', $reservation->id, [ - 'service_id' => $service->id, + 'service_id' => $lockedService->id, + 'invoice_id' => $lockedInvoice?->id, 'user_id' => $user->id, 'configuration_fingerprint' => $reservation->configuration_fingerprint, ]); }, 5); } + /** + * Turn an invoice-backed hold into a durable, non-expiring fulfillment + * commitment. The caller is responsible for running this inside the same + * transaction that marks the invoice paid. + */ + public function preflightPaidService( + Service $service, + Invoice $invoice + ): ?string { + try { + $hasBoundReservation = $this->hasCheckoutReservation( + (int) $service->id + ); + if ( + ! $hasBoundReservation + && ! $this->configurationService->requiresReservation( + (int) $service->product_id + ) + ) { + return null; + } + + $this->configurationService->assertExclusiveProvisioningControl(); + + DB::transaction(function () use ($service, $invoice): void { + $lockedInvoice = Invoice::query() + ->whereKey($invoice->id) + ->lockForUpdate() + ->firstOrFail(); + $lockedService = Service::query() + ->whereKey($service->id) + ->lockForUpdate() + ->firstOrFail(); + $reservation = $this->checkoutCommitmentQuery( + $lockedService->id + ) + ->lockForUpdate() + ->first(); + if ($reservation === null) { + throw new \RuntimeException( + 'A paid dynamic resource service has no capacity reservation.' + ); + } + if ( + $reservation->invoice_id !== null + && (int) $reservation->invoice_id + !== (int) $lockedInvoice->id + ) { + throw new \RuntimeException( + 'The paid invoice does not own this capacity commitment.' + ); + } + if (in_array($reservation->status, [ + ResourceReservation::STATUS_PAID_COMMITTED, + ResourceReservation::STATUS_CONFIRMED, + ], true)) { + return; + } + if ($reservation->status !== ResourceReservation::STATUS_PENDING) { + throw new \RuntimeException( + "Cannot commit a {$reservation->status} capacity reservation after payment." + ); + } + + $guaranteedUntil = Carbon::parse( + $reservation->guaranteed_until + ?? $reservation->expires_at + ); + if ($guaranteedUntil->isPast()) { + throw new \RuntimeException( + 'The seven-day capacity guarantee expired before payment completed.' + ); + } + + $this->assertInvoiceLineMatchesReservation( + $lockedService, + $lockedInvoice, + $reservation + ); + $this->configurationService->assertServiceMatches( + $lockedService, + $reservation + ); + $this->assertAllocationClaimsMatch( + $reservation, + true + ); + }, 5); + + return null; + } catch (\Throwable $exception) { + return "Capacity-backed service {$service->id} failed payment preflight: {$exception->getMessage()}"; + } + } + + public function commitPaidService(Service $service, Invoice $invoice): bool + { + $hasBoundReservation = $this->hasCheckoutReservation((int) $service->id); + if ( + ! $hasBoundReservation + && ! $this->configurationService->requiresReservation((int) $service->product_id) + ) { + return false; + } + + $this->configurationService->assertExclusiveProvisioningControl(); + + return DB::transaction(function () use ($service, $invoice) { + $lockedInvoice = Invoice::query() + ->whereKey($invoice->id) + ->lockForUpdate() + ->firstOrFail(); + $lockedService = Service::query()->whereKey($service->id)->lockForUpdate()->firstOrFail(); + $reservation = $this->checkoutCommitmentQuery($lockedService->id) + ->lockForUpdate() + ->first(); + + if ($reservation === null) { + throw new \RuntimeException( + 'A paid dynamic resource service has no capacity reservation.' + ); + } + + if ($reservation->invoice_id !== null && (int) $reservation->invoice_id !== (int) $lockedInvoice->id) { + throw new \RuntimeException('The paid invoice does not own this capacity commitment.'); + } + + if ($reservation->status === ResourceReservation::STATUS_PENDING) { + $this->assertInvoiceLineMatchesReservation( + $lockedService, + $lockedInvoice, + $reservation + ); + } + + if ($reservation->status === ResourceReservation::STATUS_CONFIRMED) { + $cancellationRequested = $reservation->cancellation_requested_at !== null + || $lockedService->cancellation()->where('type', 'immediate')->exists() + || in_array($lockedService->status, [ + Service::STATUS_CANCELLED, + Service::STATUS_CANCELLATION_PENDING, + ], true); + if (! $cancellationRequested) { + $lockedService->status = Service::STATUS_ACTIVE; + $this->persistFulfillmentService($lockedService); + } + + return true; + } + + if ($reservation->status === ResourceReservation::STATUS_PAID_COMMITTED) { + if (! in_array($lockedService->status, ['active', 'cancelled', 'cancellation_pending'], true)) { + $lockedService->status = 'provisioning'; + $this->persistFulfillmentService($lockedService); + } + + return true; + } + + if ($reservation->status !== ResourceReservation::STATUS_PENDING) { + throw new \RuntimeException( + "Cannot commit a {$reservation->status} capacity reservation after payment." + ); + } + + $guaranteedUntil = Carbon::parse( + $reservation->guaranteed_until ?? $reservation->expires_at + ); + if ($guaranteedUntil->isPast()) { + throw new \RuntimeException( + 'The seven-day capacity guarantee expired before payment completed.' + ); + } + + $this->configurationService->assertServiceMatches($lockedService, $reservation); + $this->assertAllocationClaimsMatch($reservation, true); + + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ + 'invoice_id' => $lockedInvoice->id, + 'status' => ResourceReservation::STATUS_PAID_COMMITTED, + 'paid_committed_at' => now(), + 'next_provisioning_attempt_at' => now(), + 'updated_at' => now(), + ]); + + $lockedService->status = 'provisioning'; + if ($lockedService->expires_at === null) { + $lockedService->expires_at = $lockedService->calculateNextDueDate(); + } + $this->persistFulfillmentService($lockedService); + + $this->safeAudit('reservation_paid_committed', 'resource_reservation', $reservation->id, [ + 'service_id' => $lockedService->id, + 'invoice_id' => $lockedInvoice->id, + 'guaranteed_until' => $guaranteedUntil->toIso8601String(), + ]); + + return true; + }, 5); + } + + /** + * Free services have no invoice but require the same durable fulfillment + * state before a queue worker may create a server. + */ + public function commitFreeService(Service $service): bool + { + $hasBoundReservation = $this->hasCheckoutReservation((int) $service->id); + if ( + ! $hasBoundReservation + && ! $this->configurationService->requiresReservation((int) $service->product_id) + ) { + return false; + } + + $this->configurationService->assertExclusiveProvisioningControl(); + + return DB::transaction(function () use ($service) { + $lockedService = Service::query()->whereKey($service->id)->lockForUpdate()->firstOrFail(); + $reservation = $this->checkoutCommitmentQuery($lockedService->id) + ->lockForUpdate() + ->first(); + + if ($reservation === null) { + throw new \RuntimeException( + 'A free dynamic resource service has no capacity reservation.' + ); + } + + if (! in_array($reservation->status, [ + ResourceReservation::STATUS_PENDING, + ResourceReservation::STATUS_PAID_COMMITTED, + ResourceReservation::STATUS_CONFIRMED, + ], true)) { + throw new \RuntimeException("Cannot fulfill a {$reservation->status} free-service reservation."); + } + + $this->configurationService->assertServiceMatches($lockedService, $reservation); + if ($reservation->status === ResourceReservation::STATUS_PENDING) { + $this->assertAllocationClaimsMatch($reservation, true); + } + + if ($reservation->status === ResourceReservation::STATUS_PENDING) { + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ + 'status' => ResourceReservation::STATUS_PAID_COMMITTED, + 'paid_committed_at' => now(), + 'next_provisioning_attempt_at' => now(), + 'updated_at' => now(), + ]); + } + + if ($reservation->status !== ResourceReservation::STATUS_CONFIRMED) { + $lockedService->status = 'provisioning'; + $lockedService->expires_at ??= $lockedService->calculateNextDueDate(); + $this->persistFulfillmentService($lockedService); + } + + return true; + }, 5); + } + /** * Lock and validate a hold immediately before the external create request. * @@ -299,35 +779,46 @@ public function bindCartItemToService( * cpu: int, * disk: int, * provisioning_lease_id: string|null, - * already_consumed: bool + * already_consumed: bool, + * nest_id: int, + * egg_id: int, + * user_external_id: string * }|null */ public function beginProvisioning(Service $service): ?array { return DB::transaction(function () use ($service) { - $reservation = DB::table('ptero_resource_reservations') - ->where('service_id', $service->id) + $reservation = $this->checkoutCommitmentQuery((int) $service->id) ->lockForUpdate() ->first(); if ($reservation === null) { if ($this->configurationService->requiresReservation($service->product_id)) { - throw new \RuntimeException('Dynamic resource service has no capacity reservation.'); + throw new PermanentProvisioningException( + 'Dynamic resource service has no capacity reservation.' + ); } return null; } + $this->assertAllocationClaimsMatch( + $reservation, + $reservation->status === ResourceReservation::STATUS_PAID_COMMITTED + ); + if ($reservation->status === 'confirmed') { return $this->provisioningContext($reservation, true); } - if ($reservation->status !== 'pending') { - throw new \RuntimeException("Capacity reservation is {$reservation->status}."); + if ($reservation->status !== ResourceReservation::STATUS_PAID_COMMITTED) { + throw new PermanentProvisioningException( + "Capacity reservation is {$reservation->status}." + ); } - if (Carbon::parse($reservation->expires_at)->isPast()) { - throw new \RuntimeException('Capacity reservation expired before provisioning.'); + if ($reservation->cancellation_requested_at !== null) { + throw new \RuntimeException('Capacity fulfillment was cancelled before provisioning.'); } if ( @@ -338,7 +829,15 @@ public function beginProvisioning(Service $service): ?array throw new \RuntimeException('Capacity reservation is already being provisioned.'); } - $this->configurationService->assertServiceMatches($service, $reservation); + try { + $this->configurationService->assertServiceMatches($service, $reservation); + } catch (\RuntimeException $exception) { + throw new PermanentProvisioningException( + $exception->getMessage(), + (int) $exception->getCode(), + $exception + ); + } $leaseExpiresAt = now()->addMinutes(self::PROVISIONING_LEASE_MINUTES); $currentExpiresAt = Carbon::parse($reservation->expires_at); @@ -352,6 +851,9 @@ public function beginProvisioning(Service $service): ?array 'expires_at' => $currentExpiresAt->greaterThan($leaseExpiresAt) ? $currentExpiresAt : $leaseExpiresAt, + 'provisioning_attempts' => (int) $reservation->provisioning_attempts + 1, + 'last_provisioning_attempt_at' => now(), + 'next_provisioning_attempt_at' => null, 'last_provisioning_error' => null, 'updated_at' => now(), ]); @@ -360,11 +862,24 @@ public function beginProvisioning(Service $service): ?array }, 5); } - public function completeProvisioning(int $serviceId, ?string $leaseId = null): bool + /** + * Confirm the exact external server and activate the Paymenter service. + * A false result means cancellation won the race and the caller must delete + * the external server rather than exposing it to the customer. + * + * @param array $externalServer + */ + public function completeProvisioning( + int|Service $service, + ?string $leaseId = null, + array $externalServer = [] + ): bool { - return DB::transaction(function () use ($serviceId, $leaseId) { - $reservation = DB::table('ptero_resource_reservations') - ->where('service_id', $serviceId) + $serviceId = $service instanceof Service ? (int) $service->id : $service; + + return DB::transaction(function () use ($serviceId, $leaseId, $externalServer) { + $lockedService = Service::query()->whereKey($serviceId)->lockForUpdate()->firstOrFail(); + $reservation = $this->checkoutCommitmentQuery($serviceId) ->lockForUpdate() ->first(); @@ -373,10 +888,18 @@ public function completeProvisioning(int $serviceId, ?string $leaseId = null): b } if ($reservation->status === 'confirmed') { - return true; + $alreadyCancelled = $reservation->cancellation_requested_at !== null + || $lockedService->cancellation()->where('type', 'immediate')->exists() + || $lockedService->status === 'cancelled'; + if (! $alreadyCancelled) { + $lockedService->status = Service::STATUS_ACTIVE; + $this->persistFulfillmentService($lockedService); + } + + return ! $alreadyCancelled; } - if ($reservation->status !== 'pending') { + if ($reservation->status !== ResourceReservation::STATUS_PAID_COMMITTED) { throw new \RuntimeException("Cannot consume a {$reservation->status} capacity reservation."); } @@ -388,17 +911,46 @@ public function completeProvisioning(int $serviceId, ?string $leaseId = null): b throw new \RuntimeException('Provisioning lease no longer owns this capacity reservation.'); } + $cancellationRequested = $reservation->cancellation_requested_at !== null + || $lockedService->status === 'cancelled' + || $lockedService->cancellation()->where('type', 'immediate')->exists(); + $externalAttributes = $externalServer['attributes'] ?? $externalServer; + $externalIdentity = $this->externalServerIdentity($externalAttributes); + + if ($cancellationRequested) { + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ + 'cancellation_requested_at' => $reservation->cancellation_requested_at ?? now(), + ...$externalIdentity, + 'last_reconciled_at' => now(), + 'provisioning_started_at' => null, + 'provisioning_lease_id' => null, + 'updated_at' => now(), + ]); + $lockedService->status = 'cancellation_pending'; + $this->persistFulfillmentService($lockedService); + + return false; + } + DB::table('ptero_resource_reservations') ->where('id', $reservation->id) ->update([ 'status' => 'confirmed', 'consumed_at' => now(), + ...$externalIdentity, + 'last_reconciled_at' => now(), 'provisioning_started_at' => null, 'provisioning_lease_id' => null, 'last_provisioning_error' => null, 'updated_at' => now(), ]); + $this->releaseAllocationClaims((int) $reservation->id); + $lockedService->status = Service::STATUS_ACTIVE; + $this->persistFulfillmentService($lockedService); + $this->safeAudit('reservation_consumed', 'resource_reservation', $reservation->id, [ 'service_id' => $serviceId, 'node_id' => $reservation->node_id, @@ -415,18 +967,348 @@ public function failProvisioning( \Throwable $exception ): void { - DB::table('ptero_resource_reservations') - ->where('service_id', $serviceId) - ->where('status', 'pending') + $attempts = (int) $this->checkoutCommitmentQuery($serviceId) + ->value('provisioning_attempts'); + $delay = self::RETRY_DELAYS_SECONDS[ + min(max(0, $attempts - 1), count(self::RETRY_DELAYS_SECONDS) - 1) + ]; + + $this->checkoutCommitmentQuery($serviceId) + ->where('status', ResourceReservation::STATUS_PAID_COMMITTED) ->where('provisioning_lease_id', $leaseId) ->update([ 'provisioning_started_at' => null, 'provisioning_lease_id' => null, + 'next_provisioning_attempt_at' => now()->addSeconds($delay), 'last_provisioning_error' => Str::limit($exception->getMessage(), 1000, ''), 'updated_at' => now(), ]); } + /** + * Persist a cancellation tombstone before any asynchronous delete runs. + * + * Returns true when the service has a dynamic reservation. + */ + public function requestServiceCancellation(Service $service): bool + { + return DB::transaction(function () use ($service) { + $lockedService = Service::query()->whereKey($service->id)->lockForUpdate()->firstOrFail(); + $reservation = $this->checkoutCommitmentQuery($lockedService->id) + ->lockForUpdate() + ->first(); + + if ($reservation === null) { + return false; + } + + if ($reservation->status === ResourceReservation::STATUS_PENDING) { + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ + 'status' => ResourceReservation::STATUS_CANCELLED, + 'cancellation_requested_at' => now(), + 'provisioning_started_at' => null, + 'provisioning_lease_id' => null, + 'admin_notes' => 'Service cancelled before payment.', + 'updated_at' => now(), + ]); + $this->releaseAllocationClaims((int) $reservation->id); + $this->releaseProductStockOnce($reservation, $lockedService); + $lockedService->status = Service::STATUS_CANCELLED; + $this->persistFulfillmentService($lockedService); + + return true; + } + + if ($reservation->status === ResourceReservation::STATUS_CANCELLED) { + return true; + } + + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ + 'cancellation_requested_at' => $reservation->cancellation_requested_at ?? now(), + 'updated_at' => now(), + ]); + $lockedService->status = 'cancellation_pending'; + $this->persistFulfillmentService($lockedService); + + return true; + }, 5); + } + + /** + * Finish cancellation only after the provisioner has established that the + * external server is absent. + */ + public function completeServiceCancellation(int|Service $service): bool + { + $serviceId = $service instanceof Service ? (int) $service->id : $service; + + return DB::transaction(function () use ($serviceId) { + $lockedService = Service::query()->whereKey($serviceId)->lockForUpdate()->firstOrFail(); + $reservation = $this->checkoutCommitmentQuery($serviceId) + ->lockForUpdate() + ->first(); + + if ($reservation === null) { + $lockedService->status = Service::STATUS_CANCELLED; + $this->persistFulfillmentService($lockedService); + + return false; + } + + if ( + $reservation->provisioning_started_at !== null + && Carbon::parse($reservation->provisioning_started_at) + ->greaterThan(now()->subMinutes(self::PROVISIONING_LEASE_MINUTES)) + ) { + throw new \RuntimeException('Provisioning is still in flight; cancellation will retry.'); + } + + if ($reservation->status !== ResourceReservation::STATUS_CONFIRMED) { + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ + 'status' => ResourceReservation::STATUS_CANCELLED, + 'cancellation_requested_at' => $reservation->cancellation_requested_at ?? now(), + 'provisioning_started_at' => null, + 'provisioning_lease_id' => null, + 'next_provisioning_attempt_at' => null, + 'updated_at' => now(), + ]); + $this->releaseAllocationClaims((int) $reservation->id); + } + + $this->releaseProductStockOnce($reservation, $lockedService); + $lockedService->status = Service::STATUS_CANCELLED; + $this->persistFulfillmentService($lockedService); + + return true; + }, 5); + } + + public function provisioningMayContinue(int $serviceId, ?string $leaseId): bool + { + if ($leaseId === null) { + return false; + } + + return $this->checkoutCommitmentQuery($serviceId) + ->where('status', ResourceReservation::STATUS_PAID_COMMITTED) + ->where('provisioning_lease_id', $leaseId) + ->whereNull('cancellation_requested_at') + ->exists(); + } + + /** + * Reservation history is deliberately permanent. Administrative and API + * entry points use this check to prevent a local hard-delete or raw + * extension action from bypassing fulfillment and orphaning a server. + */ + public function hasCheckoutReservation(int $serviceId): bool + { + return DB::table('ptero_resource_reservations') + ->where('purpose', 'checkout') + ->where('service_id', $serviceId) + ->exists(); + } + + /** + * Return the immutable identity that every post-provisioning lifecycle + * action must prove before it controls an external server. + * + * @return array|null + */ + public function serverLifecycleIdentity(int|Service $service): ?array + { + $serviceId = $service instanceof Service + ? (int) $service->id + : $service; + $reservation = $this->checkoutCommitmentQuery($serviceId)->first(); + if ($reservation === null) { + return null; + } + + try { + $payload = json_decode( + (string) $reservation->configuration_payload, + true, + 512, + JSON_THROW_ON_ERROR + ); + } catch (\JsonException $exception) { + throw new PermanentProvisioningException( + 'The durable server identity snapshot is unreadable.', + previous: $exception + ); + } + if ( + ! is_array($payload) + || ! is_string($reservation->configuration_fingerprint) + || ! hash_equals( + $reservation->configuration_fingerprint, + $this->configurationService->fingerprint($payload) + ) + ) { + throw new PermanentProvisioningException( + 'The durable server identity snapshot failed its integrity check.' + ); + } + + $provisioning = (array) ( + $payload['provisioning_identity'] ?? [] + ); + + return [ + 'reservation_id' => (int) $reservation->id, + 'status' => (string) $reservation->status, + 'panel_identity' => (string) $reservation->panel_identity, + 'node_id' => (int) $reservation->node_id, + 'external_server_id' => $reservation->external_server_id !== null + ? (int) $reservation->external_server_id + : null, + 'external_user_id' => $reservation->external_user_id !== null + ? (int) $reservation->external_user_id + : null, + 'external_server_uuid' => $reservation->external_server_uuid, + 'external_server_identifier' => + $reservation->external_server_identifier, + 'external_server_external_id' => (string) $serviceId, + 'user_external_id' => $provisioning['user_external_id'] ?? null, + 'user_email' => $provisioning['user_email'] ?? null, + 'nest_id' => $provisioning['nest_id'] ?? null, + 'egg_id' => $provisioning['egg_id'] ?? null, + ]; + } + + /** + * Called by CreateJob::failed(). The paid commitment remains reserved. + * + * @return array|null + */ + public function recordPermanentProvisioningFailure(Service $service, \Throwable $exception): ?array + { + return DB::transaction(function () use ($service, $exception) { + $lockedService = Service::query() + ->whereKey($service->id) + ->lockForUpdate() + ->firstOrFail(); + $reservation = $this->checkoutCommitmentQuery($lockedService->id) + ->lockForUpdate() + ->first(); + + if ($reservation === null || $reservation->status !== ResourceReservation::STATUS_PAID_COMMITTED) { + return null; + } + + $permanent = $exception instanceof PermanentProvisioningException; + $snapshot = [ + 'permanent' => $permanent, + 'reservation_id' => (int) $reservation->id, + 'service_id' => (int) $lockedService->id, + 'invoice_id' => $reservation->invoice_id !== null ? (int) $reservation->invoice_id : null, + 'node_id' => (int) $reservation->node_id, + 'memory' => (int) $reservation->memory, + 'cpu' => (int) $reservation->cpu, + 'disk' => (int) $reservation->disk, + 'attempts' => (int) $reservation->provisioning_attempts, + 'error' => Str::limit($exception->getMessage(), 1000, ''), + ]; + + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ + 'provisioning_started_at' => null, + 'provisioning_lease_id' => null, + 'last_provisioning_error' => $snapshot['error'], + 'next_provisioning_attempt_at' => $permanent ? null : now()->addHour(), + 'failure_alerted_at' => $reservation->failure_alerted_at ?? now(), + 'updated_at' => now(), + ]); + + if ($permanent) { + $lockedService->status = Service::STATUS_PROVISIONING_FAILED; + $this->persistFulfillmentService($lockedService); + } + + if ($reservation->failure_alerted_at === null) { + app(AlertService::class)->notifyProvisioningFailure($snapshot); + } + + return $snapshot; + }, 5); + } + + /** + * Called by TerminateJob::failed(). The cancellation tombstone remains in + * place so neither a retrying create job nor a duplicate payment can expose + * the server. + * + * @return array|null + */ + public function recordPermanentCancellationFailure( + Service $service, + \Throwable $exception + ): ?array { + return DB::transaction(function () use ($service, $exception) { + $reservation = $this->checkoutCommitmentQuery((int) $service->id) + ->lockForUpdate() + ->first(); + + if ($reservation === null || $reservation->cancellation_requested_at === null) { + return null; + } + + $snapshot = [ + 'operation' => 'cancellation', + 'reservation_id' => (int) $reservation->id, + 'service_id' => (int) $service->id, + 'invoice_id' => $reservation->invoice_id !== null ? (int) $reservation->invoice_id : null, + 'node_id' => (int) $reservation->node_id, + 'attempts' => 8, + 'error' => Str::limit($exception->getMessage(), 1000, ''), + ]; + + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ + 'last_cancellation_error' => $snapshot['error'], + 'cancellation_failure_alerted_at' => $reservation->cancellation_failure_alerted_at ?? now(), + 'updated_at' => now(), + ]); + + if ($reservation->cancellation_failure_alerted_at === null) { + app(AlertService::class)->notifyProvisioningFailure($snapshot); + } + + return $snapshot; + }, 5); + } + + public function markCustomerNotified(int $serviceId): ?bool + { + if (! $this->checkoutCommitmentQuery($serviceId)->exists()) { + return null; + } + + return $this->checkoutCommitmentQuery($serviceId) + ->whereNull('customer_notified_at') + ->update([ + 'customer_notified_at' => now(), + 'updated_at' => now(), + ]) > 0; + } + + public function customerNotificationPending(int $serviceId): ?bool + { + $reservation = $this->checkoutCommitmentQuery($serviceId) + ->first(['customer_notified_at']); + + return $reservation === null ? null : $reservation->customer_notified_at === null; + } + public function cancelForCartItem(int $cartItemId): bool { return DB::transaction(function () use ($cartItemId) { @@ -440,13 +1322,18 @@ public function cancelForCartItem(int $cartItemId): bool return false; } - return DB::table('ptero_resource_reservations') + $updated = DB::table('ptero_resource_reservations') ->where('id', $reservation->id) ->update([ 'status' => 'cancelled', 'admin_notes' => 'Cart item removed.', 'updated_at' => now(), ]) > 0; + if ($updated) { + $this->releaseAllocationClaims((int) $reservation->id); + } + + return $updated; }, 5); } @@ -482,6 +1369,7 @@ public function cancel( ]) > 0; if ($updated) { + $this->releaseAllocationClaims((int) $reservation->id); $this->safeAudit('reservation_cancelled', 'resource_reservation', $reservation->id, [ 'source' => $source, 'node_id' => $reservation->node_id, @@ -509,7 +1397,12 @@ public function extend(string $token, int $additionalMinutes = 15, ?User $actor return false; } + if ($reservation->service_id !== null || $reservation->invoice_id !== null) { + return false; + } + $reservation->expires_at = $reservation->expires_at->addMinutes($additionalMinutes); + $reservation->guaranteed_until = $reservation->expires_at; $reservation->save(); $this->safeAudit('reservation_extended', 'resource_reservation', $reservation->id, [ @@ -610,15 +1503,233 @@ public function getStatistics(string $period = '30d'): array public function cleanupExpired(): int { - $count = DB::table('ptero_resource_reservations') + $candidateIds = DB::table('ptero_resource_reservations') + ->where('purpose', 'checkout') ->where('status', 'pending') - ->where('expires_at', '<', now()) - ->update([ - 'status' => 'expired', - 'provisioning_started_at' => null, - 'provisioning_lease_id' => null, - 'updated_at' => now(), - ]); + ->whereRaw('COALESCE(guaranteed_until, expires_at) <= ?', [now()]) + ->pluck('id'); + $count = 0; + + foreach ($candidateIds as $candidateId) { + $changed = DB::transaction(function () use ($candidateId) { + $candidate = DB::table('ptero_resource_reservations')->where('id', $candidateId)->first(); + if ($candidate === null) { + return false; + } + + $invoice = $candidate->invoice_id !== null + ? Invoice::query()->whereKey($candidate->invoice_id)->lockForUpdate()->first() + : null; + $itemSnapshotIds = $invoice !== null + ? $invoice->items()->orderBy('id')->pluck('id') + : collect(); + $serviceIds = $invoice !== null + ? $invoice->items() + ->where('reference_type', Service::class) + ->pluck('reference_id') + ->merge( + DB::table('ptero_resource_reservations') + ->where('purpose', 'checkout') + ->where('invoice_id', $invoice->id) + ->pluck('service_id') + ) + ->filter() + ->map(fn ($id) => (int) $id) + ->unique() + ->sort() + ->values() + : collect(array_filter([(int) ($candidate->service_id ?? 0)])); + $services = Service::query() + ->whereKey($serviceIds->all()) + ->orderBy('id') + ->lockForUpdate() + ->get(); + $service = $services->firstWhere('id', (int) $candidate->service_id); + $reservations = DB::table('ptero_resource_reservations') + ->where('purpose', 'checkout') + ->when( + $invoice !== null, + fn (Builder $query) => $query->where( + 'invoice_id', + $invoice->id + ), + fn (Builder $query) => $query->where('id', $candidateId) + ) + ->orderBy('id') + ->lockForUpdate() + ->get(); + $reservation = $reservations->firstWhere('id', $candidateId); + $lockedItems = $invoice !== null + ? $invoice->items() + ->orderBy('id') + ->lockForUpdate() + ->get() + : collect(); + if ( + $invoice !== null + && $lockedItems->pluck('id')->all() + !== $itemSnapshotIds->all() + ) { + throw new \RuntimeException( + 'The capacity invoice obligations changed while expiry was acquiring its locks.' + ); + } + + if ( + $reservation === null + || $reservation->status !== ResourceReservation::STATUS_PENDING + || Carbon::parse( + $reservation->guaranteed_until ?? $reservation->expires_at + )->isFuture() + ) { + return false; + } + + if ($invoice?->status === Invoice::STATUS_PAID && $service !== null) { + $reason = 'A paid invoice was found after its capacity guarantee expired before fulfillment was committed.'; + $snapshot = [ + 'reservation_id' => (int) $reservation->id, + 'service_id' => (int) $service->id, + 'invoice_id' => (int) $invoice->id, + 'node_id' => (int) $reservation->node_id, + 'memory' => (int) $reservation->memory, + 'cpu' => (int) $reservation->cpu, + 'disk' => (int) $reservation->disk, + 'attempts' => (int) $reservation->provisioning_attempts, + 'error' => $reason, + ]; + $expiringReservations = $reservations->where( + 'status', + ResourceReservation::STATUS_PENDING + ); + foreach ($expiringReservations as $expiringReservation) { + DB::table('ptero_resource_reservations') + ->where('id', $expiringReservation->id) + ->update([ + 'status' => ResourceReservation::STATUS_EXPIRED, + 'last_provisioning_error' => $reason, + 'failure_alerted_at' => $expiringReservation->failure_alerted_at ?? now(), + 'admin_notes' => $reason, + 'updated_at' => now(), + ]); + $this->releaseAllocationClaims( + (int) $expiringReservation->id + ); + } + foreach ($services as $linkedService) { + if ($linkedService->status !== Service::STATUS_PENDING) { + continue; + } + $linkedReservation = $reservations->firstWhere( + 'service_id', + $linkedService->id + ); + if ($linkedReservation !== null) { + $this->releaseProductStockOnce( + $linkedReservation, + $linkedService + ); + } else { + app(ProductStockService::class)->release( + $linkedService + ); + } + $linkedService->status = Service::STATUS_PROVISIONING_FAILED; + $this->persistFulfillmentService($linkedService); + } + + if ($reservation->failure_alerted_at === null) { + DB::afterCommit(function () use ($snapshot, $reason) { + $alerts = app(AlertService::class); + if (method_exists($alerts, 'notifyShortfall')) { + $alerts->notifyShortfall( + $snapshot['service_id'], + $snapshot['invoice_id'], + $snapshot, + $reason + ); + } else { + $alerts->notifyProvisioningFailure($snapshot); + } + }); + } + + return true; + } + + if ( + $invoice?->status === Invoice::STATUS_PAID + || $service?->status === 'provisioning' + ) { + throw new \RuntimeException( + 'An expired hold cannot be reclaimed after payment or provisioning begins.' + ); + } + + $paymentAttention = $invoice !== null + && $invoice->status === Invoice::STATUS_PENDING + && app(CapacityInvoicePaymentService::class) + ->hasInFlightOrSucceededPayment($invoice); + + foreach ( + $reservations->where( + 'status', + ResourceReservation::STATUS_PENDING + ) as $expiringReservation + ) { + DB::table('ptero_resource_reservations') + ->where('id', $expiringReservation->id) + ->update([ + 'status' => ResourceReservation::STATUS_EXPIRED, + 'provisioning_started_at' => null, + 'provisioning_lease_id' => null, + 'updated_at' => now(), + ]); + $this->releaseAllocationClaims( + (int) $expiringReservation->id + ); + } + + if ($paymentAttention) { + app(CapacityInvoicePaymentService::class)->requireAttention( + $invoice, + 'The seven-day capacity guarantee expired after a partial or in-flight payment. Capacity was released; refund or account-credit review is required.' + ); + } elseif ($invoice !== null && $invoice->status === Invoice::STATUS_PENDING) { + app(CancelInvoiceService::class) + ->markCancelledAfterFulfillment($invoice); + } + foreach ($services as $linkedService) { + if ($linkedService->status !== Service::STATUS_PENDING) { + continue; + } + + $linkedService->status = $paymentAttention + ? Service::STATUS_PROVISIONING_FAILED + : Service::STATUS_CANCELLED; + $this->persistFulfillmentService($linkedService); + + $linkedReservation = $reservations->firstWhere( + 'service_id', + $linkedService->id + ); + if ($linkedReservation !== null) { + $this->releaseProductStockOnce( + $linkedReservation, + $linkedService + ); + } else { + app(ProductStockService::class)->release($linkedService); + } + } + + return true; + }, 5); + + if ($changed) { + $count++; + } + } if ($count > 0) { $this->safeAudit('reservations_expired_batch', 'resource_reservation', 0, [ @@ -630,13 +1741,106 @@ public function cleanupExpired(): int return $count; } + /** + * Requeue durable paid commitments that are not currently leased. + * The extension schedule can call this independently of queue retry state. + */ + public function reconcileStalledPaidCommitments(int $limit = 100): int + { + $cutoff = now()->subMinutes(self::PROVISIONING_LEASE_MINUTES); + $reservationIds = DB::table('ptero_resource_reservations') + ->where('status', ResourceReservation::STATUS_PAID_COMMITTED) + ->whereNull('cancellation_requested_at') + ->where(function (Builder $query) { + $query->whereNull('next_provisioning_attempt_at') + ->orWhere('next_provisioning_attempt_at', '<=', now()); + }) + ->where(function (Builder $query) use ($cutoff) { + $query->whereNull('provisioning_started_at') + ->orWhere('provisioning_started_at', '<=', $cutoff); + }) + ->orderBy('next_provisioning_attempt_at') + ->limit($limit) + ->pluck('id'); + + $dispatched = 0; + foreach ($reservationIds as $reservationId) { + $service = DB::transaction(function () use ($reservationId, $cutoff) { + $candidate = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->first(['service_id']); + if ($candidate?->service_id === null) { + return null; + } + + $service = Service::query() + ->whereKey($candidate->service_id) + ->lockForUpdate() + ->first(); + $reservation = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->lockForUpdate() + ->first(); + if ( + $service === null + || $service->status !== Service::STATUS_PROVISIONING + || $reservation === null + || $reservation->status !== ResourceReservation::STATUS_PAID_COMMITTED + || $reservation->cancellation_requested_at !== null + || ( + $reservation->next_provisioning_attempt_at !== null + && Carbon::parse($reservation->next_provisioning_attempt_at)->isFuture() + ) + || ( + $reservation->provisioning_started_at !== null + && Carbon::parse($reservation->provisioning_started_at)->greaterThan($cutoff) + ) + ) { + return null; + } + + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'provisioning_started_at' => null, + 'provisioning_lease_id' => null, + 'next_provisioning_attempt_at' => now()->addMinutes(10), + 'updated_at' => now(), + ]); + + return $service; + }, 5); + + if ($service === null) { + continue; + } + + if (class_exists(\App\Jobs\Server\CreateJob::class)) { + \App\Jobs\Server\CreateJob::dispatch($service); + $dispatched++; + } + } + + return $dispatched; + } + /** * @param object $reservation * @param array $snapshot */ private function matchesSnapshot(object $reservation, array $snapshot): bool { - $payload = $this->configurationService->withNode($snapshot, (int) $reservation->node_id); + $storedPayload = json_decode( + (string) $reservation->configuration_payload, + true, + 512, + JSON_THROW_ON_ERROR + ); + $payload = $this->configurationService->withPlacement( + $snapshot, + (int) $reservation->node_id, + (array) ($storedPayload['allocations'] ?? []) + ); return hash_equals( (string) $reservation->configuration_fingerprint, @@ -655,7 +1859,11 @@ private function matchesSnapshot(object $reservation, array $snapshot): bool * cpu: int, * disk: int, * provisioning_lease_id: string|null, - * already_consumed: bool + * already_consumed: bool, + * allocations: array>, + * nest_id: int, + * egg_id: int, + * user_external_id: string * } */ private function provisioningContext( @@ -664,6 +1872,56 @@ private function provisioningContext( ?string $leaseId = null ): array { + try { + $payload = json_decode( + (string) $reservation->configuration_payload, + true, + 512, + JSON_THROW_ON_ERROR + ); + } catch (\JsonException $exception) { + throw new PermanentProvisioningException( + 'The capacity reservation provisioning identity is unreadable.', + previous: $exception + ); + } + $identity = is_array($payload) + ? (array) ($payload['provisioning_identity'] ?? []) + : []; + $nestId = \App\Support\StrictInteger::parse( + $identity['nest_id'] ?? null + ); + $eggId = \App\Support\StrictInteger::parse( + $identity['egg_id'] ?? null + ); + $userExternalId = $identity['user_external_id'] ?? null; + if ( + $nestId === null + || $nestId <= 0 + || $eggId === null + || $eggId <= 0 + || ! is_string($userExternalId) + || $userExternalId === '' + ) { + throw new PermanentProvisioningException( + 'The capacity reservation has no valid provisioning identity.' + ); + } + + $allocations = DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservation->id) + ->orderByDesc('is_primary') + ->orderBy('id') + ->get() + ->map(fn ($allocation) => [ + 'allocation_id' => (int) $allocation->allocation_id, + 'ip' => (string) ($allocation->ip ?? ''), + 'port' => (int) $allocation->port, + 'environment_key' => $allocation->environment_key, + 'is_primary' => (bool) $allocation->is_primary, + ]) + ->all(); + return [ 'reservation_id' => (int) $reservation->id, 'panel_identity' => (string) $reservation->panel_identity, @@ -674,6 +1932,366 @@ private function provisioningContext( 'disk' => (int) $reservation->disk, 'provisioning_lease_id' => $leaseId, 'already_consumed' => $alreadyConsumed, + 'allocations' => $allocations, + 'nest_id' => $nestId, + 'egg_id' => $eggId, + 'user_external_id' => $userExternalId, + ]; + } + + /** + * Apply the single authoritative predicate used by stock calculations. + */ + public function applyCapacityHoldingScope(Builder $query): Builder + { + return $query->where(function (Builder $query) { + $query->where(function (Builder $query) { + $query->where('status', ResourceReservation::STATUS_PENDING) + ->where('expires_at', '>', now()); + })->orWhere('status', ResourceReservation::STATUS_PAID_COMMITTED); + }); + } + + /** + * @param array> $available + * @param array> $requirements + * @return array> + */ + private function mapAllocationRequirements(array $available, array $requirements): array + { + $pool = array_values($available); + $mapped = []; + $requirements = $requirements !== [] ? array_values($requirements) : [[ + 'environment_key' => 'SERVER_PORT', + 'requested_port' => null, + 'is_primary' => true, + ]]; + + // Claim explicit ports first. Otherwise an earlier wildcard (commonly + // SERVER_PORT) could consume an allocation needed by a later fixed + // egg-variable mapping even though the node passed the quote check. + $requirements = array_values(array_merge( + array_filter( + $requirements, + fn (array $requirement): bool => + ($requirement['requested_port'] ?? null) !== null + ), + array_filter( + $requirements, + fn (array $requirement): bool => + ($requirement['requested_port'] ?? null) === null + ) + )); + + foreach ($requirements as $requirement) { + $requestedPort = $requirement['requested_port'] ?? null; + $index = null; + if ($requestedPort !== null) { + foreach ($pool as $candidateIndex => $candidate) { + if ((int) ($candidate['port'] ?? 0) === (int) $requestedPort) { + $index = $candidateIndex; + break; + } + } + if ($index === null) { + throw new DisplayException( + "The selected node does not have requested port {$requestedPort} available." + ); + } + } + $index ??= array_key_first($pool); + if ($index === null) { + throw new DisplayException('The selected node no longer has enough free allocations.'); + } + + $allocation = $pool[$index]; + unset($pool[$index]); + $pool = array_values($pool); + $mapped[] = [ + 'allocation_id' => (int) ($allocation['allocation_id'] ?? $allocation['id'] ?? 0), + 'ip' => (string) ($allocation['ip'] ?? ''), + 'port' => (int) ($allocation['port'] ?? 0), + 'environment_key' => (string) ($requirement['environment_key'] ?? 'SERVER_PORT'), + 'is_primary' => (bool) ($requirement['is_primary'] ?? false), + ]; + } + + if (! collect($mapped)->contains('is_primary', true)) { + $mapped[0]['is_primary'] = true; + } + + foreach ($mapped as $allocation) { + if ($allocation['allocation_id'] <= 0 || $allocation['port'] <= 0) { + throw new DisplayException('Pterodactyl returned an invalid allocation.'); + } + } + + return $mapped; + } + + /** + * @param array $attributes + * @return array{ + * external_server_id: int, + * external_user_id: int, + * external_server_uuid: string, + * external_server_identifier: string + * } + */ + private function externalServerIdentity(array $attributes): array + { + $id = $attributes['id'] ?? null; + $userId = $attributes['user'] ?? null; + $uuid = $attributes['uuid'] ?? null; + $identifier = $attributes['identifier'] ?? null; + + if ( + ! is_numeric($id) + || (int) $id <= 0 + || StrictInteger::parse($userId) === null + || (int) $userId <= 0 + || ! is_string($uuid) + || ! Str::isUuid($uuid) + || ! is_string($identifier) + || trim($identifier) === '' + ) { + throw new \RuntimeException( + 'Pterodactyl did not return a complete external server identity.' + ); + } + + return [ + 'external_server_id' => (int) $id, + 'external_user_id' => (int) $userId, + 'external_server_uuid' => $uuid, + 'external_server_identifier' => $identifier, ]; } + + /** + * @param array{panel_identity: string, location_id: int} $scope + */ + private function capacityScopeKey(array $scope): string + { + return $scope['panel_identity'] . ':' . $scope['location_id']; + } + + private function checkoutCommitmentQuery(int $serviceId): Builder + { + return DB::table('ptero_resource_reservations') + ->where('service_id', $serviceId) + ->where('purpose', 'checkout') + ->whereIn('status', [ + ResourceReservation::STATUS_PENDING, + ResourceReservation::STATUS_PAID_COMMITTED, + ResourceReservation::STATUS_CONFIRMED, + ]); + } + + private function assertInvoiceLineMatchesReservation( + Service $service, + Invoice $invoice, + object $reservation + ): void { + $lockedInvoice = Invoice::query() + ->whereKey($invoice->id) + ->lockForUpdate() + ->firstOrFail(); + $lines = $lockedInvoice->items() + ->where('reference_type', Service::class) + ->where('reference_id', $service->id) + ->orderBy('id') + ->lockForUpdate() + ->get(); + + if ($lines->count() !== 1) { + throw new \RuntimeException( + 'A dynamic capacity commitment requires exactly one immutable invoice line for its service.' + ); + } + + $line = $lines->first(); + $lineQuantity = (int) $line->quantity; + $lineUnitCents = $this->moneyCents($line->price); + $reservedAmountCents = $this->moneyCents( + $reservation->calculated_price + ); + $lineAmountCents = $lineUnitCents !== null + && $lineQuantity > 0 + && $lineUnitCents <= intdiv(PHP_INT_MAX, $lineQuantity) + ? $lineUnitCents * $lineQuantity + : null; + + if ( + $lineAmountCents === null + || $reservedAmountCents === null + || $lineQuantity !== (int) $reservation->quantity + || strtoupper((string) $lockedInvoice->currency_code) + !== strtoupper((string) $reservation->currency_code) + || $lineAmountCents !== $reservedAmountCents + ) { + throw new \RuntimeException( + 'The invoice line no longer matches the reserved quantity, currency, or pre-tax checkout price.' + ); + } + } + + private function moneyCents(mixed $value): ?int + { + if (is_float($value)) { + if ( + ! is_finite($value) + || $value < 0 + || abs($value - round($value, 2)) > 1e-8 + ) { + return null; + } + $value = number_format($value, 2, '.', ''); + } + + $text = is_int($value) + ? (string) $value + : (is_string($value) ? $value : ''); + if ( + preg_match('/^(0|[1-9]\d*)(?:\.(\d+))?$/D', $text, $matches) + !== 1 + ) { + return null; + } + + $whole = StrictInteger::parse($matches[1]); + $fraction = $matches[2] ?? ''; + if ( + $whole === null + || (strlen($fraction) > 2 + && trim(substr($fraction, 2), '0') !== '') + || $whole > intdiv(PHP_INT_MAX - 99, 100) + ) { + return null; + } + + return $whole * 100 + + (int) str_pad(substr($fraction, 0, 2), 2, '0'); + } + + /** + * Prove that the allocation claim rows are an exact materialization of the + * fingerprinted payload before any external request can use them. + */ + private function assertAllocationClaimsMatch(object $reservation, bool $requireActive): void + { + $payload = json_decode( + (string) $reservation->configuration_payload, + true, + 512, + JSON_THROW_ON_ERROR + ); + if ( + ! is_array($payload) + || ! hash_equals( + (string) $reservation->configuration_fingerprint, + $this->configurationService->fingerprint($payload) + ) + || (string) ($payload['panel_identity'] ?? '') !== (string) $reservation->panel_identity + || (int) ($payload['node_id'] ?? 0) !== (int) $reservation->node_id + || (int) data_get($payload, 'resources.memory', 0) !== (int) $reservation->memory + || (int) data_get($payload, 'resources.cpu', 0) !== (int) $reservation->cpu + || (int) data_get($payload, 'resources.disk', 0) !== (int) $reservation->disk + ) { + throw new PermanentProvisioningException( + 'The capacity reservation payload no longer matches its immutable fingerprint.' + ); + } + + $expected = collect($payload['allocations'] ?? []) + ->map(fn (array $allocation) => [ + 'panel_identity' => (string) $reservation->panel_identity, + 'node_id' => (int) $reservation->node_id, + 'allocation_id' => (int) ($allocation['allocation_id'] ?? 0), + 'ip' => (string) ($allocation['ip'] ?? ''), + 'port' => (int) ($allocation['port'] ?? 0), + 'environment_key' => $allocation['environment_key'] ?? null, + 'is_primary' => (bool) ($allocation['is_primary'] ?? false), + ]) + ->sortBy('allocation_id') + ->values() + ->all(); + $claims = DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservation->id) + ->lockForUpdate() + ->get(); + $actual = $claims + ->map(fn ($allocation) => [ + 'panel_identity' => (string) $allocation->panel_identity, + 'node_id' => (int) $allocation->node_id, + 'allocation_id' => (int) $allocation->allocation_id, + 'ip' => (string) ($allocation->ip ?? ''), + 'port' => (int) $allocation->port, + 'environment_key' => $allocation->environment_key, + 'is_primary' => (bool) $allocation->is_primary, + ]) + ->sortBy('allocation_id') + ->values() + ->all(); + + if ( + $expected === [] + || $expected !== $actual + || collect($actual)->where('is_primary', true)->count() !== 1 + || ( + $requireActive + && $claims->contains(fn ($allocation) => $allocation->released_at !== null) + ) + ) { + throw new PermanentProvisioningException( + 'Allocation claims no longer match the immutable capacity reservation.' + ); + } + } + + private function persistFulfillmentService(Service $service): void + { + FulfillmentStatusTransitionService::run( + $service, + fn () => $service->save() + ); + } + + private function releaseAllocationClaims(int $reservationId): void + { + DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservationId) + ->whereNull('released_at') + ->update([ + 'released_at' => now(), + 'updated_at' => now(), + ]); + } + + /** + * Return Paymenter's product-level unit exactly once. + * + * Pending orders are released when their hold is cancelled or expires. + * Paid/confirmed services reach this method only after the provisioner has + * proved that the external server is absent. + */ + private function releaseProductStockOnce( + object $reservation, + Service $service + ): bool { + $claimed = DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->whereNull('product_stock_released_at') + ->update([ + 'product_stock_released_at' => now(), + 'updated_at' => now(), + ]); + if ($claimed !== 1) { + return false; + } + + app(ProductStockService::class)->release($service); + + return true; + } } diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index ce6c485..faf017c 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -2,73 +2,54 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Services; -use App\Models\Extension; -use Illuminate\Http\Client\ConnectionException; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Http; +use Paymenter\Extensions\Others\DynamicPterodactyl\Models\NodeCapacityPolicy; +use Paymenter\Extensions\Others\DynamicPterodactyl\Models\ResourceReservation; class ResourceCalculationService { - private string $apiUrl; + private PterodactylInventoryService $inventory; - private string $apiKey; - - public function __construct() + public function __construct(?PterodactylInventoryService $inventory = null) { - $config = $this->getExtensionConfig(); - $this->apiUrl = rtrim($config['pterodactyl_url'] ?? '', '/'); - $this->apiKey = $config['pterodactyl_api_key'] ?? ''; + $this->inventory = $inventory ?? app(PterodactylInventoryService::class); } /** - * Get available resources for a location (real-time from Pterodactyl API) + * Build current stock for every node in a location. + * + * Memory and disk allocation use the greater of NodeTransformer's + * allocated_resources and the complete server index. This is deliberately + * conservative while Pterodactyl's independently-read node and server + * snapshots converge after a create or update. CPU comes from the server + * index and a local, explicit per-node capacity policy. Any missing or + * ambiguous inventory makes that node ineligible rather than optimistic. + * + * @return array */ - public function getLocationAvailability(int $locationId, ?string $excludeReservationToken = null): array - { - $nodes = $this->fetchNodesInLocation($locationId); - - $locationData = [ - 'location_id' => $locationId, - 'nodes' => [], - 'max_available' => ['memory' => 0, 'cpu' => null, 'disk' => 0], - 'total_capacity' => ['memory' => 0, 'cpu' => null, 'disk' => 0], - 'total_allocated' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], - 'cpu_capacity_enforced' => false, - ]; - - foreach ($nodes as $node) { - $nodeAvailability = $this->calculateNodeAvailability($node, $excludeReservationToken); - $locationData['nodes'][] = $nodeAvailability; - - // Track maximum available across all nodes - $locationData['max_available']['memory'] = max( - $locationData['max_available']['memory'], - $nodeAvailability['available']['memory'] - ); - $locationData['max_available']['disk'] = max( - $locationData['max_available']['disk'], - $nodeAvailability['available']['disk'] - ); - - // Aggregate totals - $locationData['total_capacity']['memory'] += $nodeAvailability['total']['memory']; - $locationData['total_capacity']['disk'] += $nodeAvailability['total']['disk']; - - $locationData['total_allocated']['memory'] += $nodeAvailability['allocated']['memory']; - $locationData['total_allocated']['cpu'] += $nodeAvailability['allocated']['cpu']; - $locationData['total_allocated']['disk'] += $nodeAvailability['allocated']['disk']; - } - - return $locationData; + public function getLocationAvailability( + int $locationId, + ?string $excludeReservationToken = null + ): array { + $nodes = $this->inventory->nodesInLocation($locationId); + + return $this->buildLocationAvailability( + $locationId, + $nodes, + $excludeReservationToken + ); } + /** + * @return array + */ public function buildClusterSnapshot(): array { $snapshot = $this->emptyClusterSnapshot(); try { - $locations = $this->fetchAllLocations(); - $nodes = $this->fetchClusterNodes(); + $locations = $this->inventory->locations(); + $nodes = $this->inventory->nodes(); } catch (\RuntimeException $exception) { if ($this->shouldReturnDegradedSnapshot($exception)) { return $this->degradedClusterSnapshot(); @@ -78,704 +59,1010 @@ public function buildClusterSnapshot(): array } $snapshot['locations'] = $locations; - $knownLocationIds = []; + $nodesByLocation = collect($nodes)->groupBy('location_id'); foreach ($locations as $location) { - $knownLocationIds[$location['id']] = true; - $snapshot['by_location'][$location['id']] = [ - 'nodes' => [], - 'totals' => ['memory' => 0, 'cpu' => null, 'disk' => 0], - 'allocated' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], - 'available' => ['memory' => 0, 'cpu' => null, 'disk' => 0], - ]; - } - - $pendingReservations = $this->getPendingReservationsForNodes(array_keys($nodes)); - - foreach ($nodes as $nodeId => $nodeData) { - $node = $nodeData['node']; - $locationId = $nodeData['location_id']; - if (! array_key_exists($locationId, $knownLocationIds)) { - throw new \RuntimeException('Pterodactyl API returned a node for an unknown location.'); - } - $availability = $this->buildNodeAvailabilityFromServers( - $node, - $nodeData['servers'], - $pendingReservations[$nodeId] ?? ['memory' => 0, 'cpu' => 0, 'disk' => 0], + $locationId = (int) $location['id']; + $locationAvailability = $this->buildLocationAvailability( + $locationId, + $nodesByLocation->get($locationId, collect())->values()->all() ); - $snapshot['nodes'][$nodeId] = [ - 'node' => $node, - 'location_id' => $locationId, - 'servers' => $nodeData['servers'], - 'totals' => $availability['total'], - 'allocated' => $availability['allocated'], - 'available' => $availability['available'], - 'reserved' => $availability['reserved'], - 'server_count' => $availability['server_count'], - 'utilization' => $availability['utilization'], - 'node_availability' => $availability, + $snapshot['by_location'][$locationId] = [ + 'nodes' => array_column($locationAvailability['nodes'], 'node_id'), + 'totals' => $locationAvailability['total_capacity'], + 'allocated' => $locationAvailability['total_allocated'], + 'available' => $locationAvailability['total_available'], ]; - $snapshot['by_location'][$locationId]['nodes'][] = $nodeId; - $snapshot['by_location'][$locationId]['totals']['memory'] += $availability['total']['memory']; - $snapshot['by_location'][$locationId]['totals']['disk'] += $availability['total']['disk']; - $snapshot['by_location'][$locationId]['allocated']['memory'] += $availability['allocated']['memory']; - $snapshot['by_location'][$locationId]['allocated']['cpu'] += $availability['allocated']['cpu']; - $snapshot['by_location'][$locationId]['allocated']['disk'] += $availability['allocated']['disk']; - $snapshot['by_location'][$locationId]['available']['memory'] += $availability['available']['memory']; - $snapshot['by_location'][$locationId]['available']['disk'] += $availability['available']['disk']; + foreach ($locationAvailability['nodes'] as $node) { + $snapshot['nodes'][$node['node_id']] = [ + 'node' => [ + 'id' => $node['node_id'], + 'uuid' => $node['node_uuid'], + 'name' => $node['name'], + 'fqdn' => $node['fqdn'], + 'public' => $node['public'], + 'maintenance_mode' => $node['maintenance_mode'], + 'location_id' => $locationId, + ], + 'location_id' => $locationId, + 'servers' => $node['servers'], + 'totals' => $node['total'], + 'allocated' => $node['allocated'], + 'available' => $node['available'], + 'reserved' => $node['reserved'], + 'server_count' => $node['server_count'], + 'utilization' => $node['utilization'], + 'node_availability' => $node, + ]; + } } return $snapshot; } /** - * Calculate available resources for a specific node + * Verify the complete resource vector against one currently eligible node. + * + * @param array{memory: int, cpu: int, disk: int} $requirements */ - private function calculateNodeAvailability(array $nodeWithServers, ?string $excludeReservationToken = null): array - { - $node = $nodeWithServers['node']; - $servers = $nodeWithServers['servers']; - $pendingReservations = $this->getPendingReservations($node['id'], $excludeReservationToken); - - return $this->buildNodeAvailabilityFromServers($node, $servers, $pendingReservations); + public function verifyAvailability( + int $nodeId, + array $requirements, + ?string $excludeReservationToken = null + ): bool { + return $this->verifyNodeCapacity( + $nodeId, + $requirements, + 1, + $excludeReservationToken + ); } /** - * Test API connection + * Verify a capacity vector on a fixed node. Existing-server upgrades call + * this with allocationCount=0 because their primary port remains assigned. + * + * @param array{memory: int, cpu: int, disk: int} $requirements */ - // Does not use pterodactylGet() — admin-initiated diagnostic needs longer timeout and different error surfaces. - public function testConnection(): array - { - try { - $response = Http::withHeaders([ - 'Authorization' => 'Bearer '.$this->apiKey, - 'Accept' => 'application/json', - ])->timeout(10)->get("{$this->apiUrl}/api/application/nodes"); - - if ($response->successful()) { - $data = $response->json(); - - if (! is_array($data) || ! is_array($data['data'] ?? null)) { - return [ - 'success' => false, - 'message' => 'Connection succeeded but response body was not a valid Pterodactyl nodes payload.', - ]; - } + public function verifyNodeCapacity( + int $nodeId, + array $requirements, + int $allocationCount = 1, + ?string $excludeReservationToken = null + ): bool { + if ($allocationCount < 0) { + throw new \InvalidArgumentException('Allocation count cannot be negative.'); + } - return [ - 'success' => true, - 'message' => 'Connection successful', - 'node_count' => count($data['data']), - 'panel_version' => $response->header('X-Pterodactyl-Version'), - ]; + foreach (['memory', 'cpu', 'disk'] as $resource) { + if ( + ! array_key_exists($resource, $requirements) + || ! is_int($requirements[$resource]) + || $requirements[$resource] < 0 + ) { + throw new \InvalidArgumentException( + 'Resource requirements must be non-negative integers.' + ); } + } - return [ - 'success' => false, - 'message' => 'API returned error: '.$response->status(), - 'details' => $response->json('errors', []), - ]; - } catch (\Exception $e) { - return [ - 'success' => false, - 'message' => 'Connection failed: '.$e->getMessage(), - ]; + $availability = $this->getNodeAvailability( + $nodeId, + $excludeReservationToken + ); + if ($availability === null) { + return false; } + + $blockingReasons = array_values(array_filter( + $availability['ineligible_reasons'], + fn (string $reason): bool => $allocationCount > 0 + || $reason !== 'no_available_allocation' + )); + + return $blockingReasons === [] + && $availability['available']['memory'] >= $requirements['memory'] + && $availability['available']['cpu'] >= $requirements['cpu'] + && $availability['available']['disk'] >= $requirements['disk'] + && count($availability['available_allocations']) >= $allocationCount; } /** - * Verify authoritative memory and disk capacity. + * Internal stock detail for fixed-node fulfillment and upgrade decisions. * - * CPU is intentionally not checked because Pterodactyl does not publish node - * CPU inventory. The requested CPU limit is still reserved as identity data - * and passed to server creation. + * @return array|null */ - public function verifyAvailability(int $nodeId, array $requirements, ?string $excludeReservationToken = null): bool - { - $nodes = $this->fetchNodesInLocation($this->getNodeLocation($nodeId)); - $nodeWithServers = \collect($nodes)->first(fn ($n) => ($n['node']['id'] ?? null) === $nodeId); - - if (! $nodeWithServers) { - return false; + public function getNodeAvailability( + int $nodeId, + ?string $excludeReservationToken = null + ): ?array { + $node = collect($this->inventory->nodes())->firstWhere('id', $nodeId); + if (! is_array($node)) { + return null; } - $availability = $this->calculateNodeAvailability($nodeWithServers, $excludeReservationToken); + $location = $this->buildLocationAvailability( + (int) $node['location_id'], + [$node], + $excludeReservationToken + ); - return $availability['available']['memory'] >= $requirements['memory'] - && $availability['available']['disk'] >= $requirements['disk']; + return $location['nodes'][0] ?? null; } /** - * Get all locations from Pterodactyl + * @return list */ public function getLocations(): array { - return $this->fetchAllLocations(); + return $this->inventory->locations(); } - // --- Private Methods --- - - private function fetchNodesInLocation(int $locationId): array + public function testConnection(): array { - $response = $this->pterodactylGet( - "/api/application/locations/{$locationId}", - ['include' => 'nodes,servers'] + return $this->inventory->testConnection(); + } + + /** + * @param list> $nodes + * @return array + */ + private function buildLocationAvailability( + int $locationId, + array $nodes, + ?string $excludeReservationToken = null + ): array { + $nodeIds = array_map(fn (array $node): int => (int) $node['id'], $nodes); + $servers = $this->inventory->serversForNodes($nodeIds); + $reservations = $this->holdingReservations( + $nodeIds, + $servers, + $excludeReservationToken + ); + $reservedAllocationClaims = $this->reservedAllocationClaims( + $nodeIds, + $excludeReservationToken ); + $policies = $this->cpuPolicies($nodes); - $nodesData = $this->requireRelationshipData($response, 'nodes'); - $serversData = $this->requireRelationshipData($response, 'servers'); + $location = [ + 'location_id' => $locationId, + 'nodes' => [], + 'max_available' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], + 'total_capacity' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], + 'total_allocated' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], + 'total_available' => ['memory' => 0, 'cpu' => 0, 'disk' => 0], + 'cpu_capacity_enforced' => true, + ]; - $nodesById = []; - foreach ($nodesData as $node) { - $attributes = $this->requireNodeAttributes($node); - if ($attributes['location_id'] !== $locationId) { - throw new \RuntimeException('Pterodactyl API returned a node for an unexpected location.'); - } - $this->rememberUniqueId($nodesById, $attributes['id'], 'included node'); - $nodesById[$attributes['id']] = $attributes; - } + foreach ($nodes as $node) { + $nodeId = (int) $node['id']; + $nodeServers = $servers[$nodeId] ?? []; + $assignedServerAllocationIds = collect($nodeServers) + ->flatMap( + fn (array $server): array => + $server['assigned_allocation_ids'] ?? [] + ) + ->map(fn ($id): int => (int) $id) + ->unique() + ->values() + ->all(); + $inventoryAllocations = + $this->inventory->availableAllocationsForNode($nodeId); + $assignedServerIps = collect($inventoryAllocations) + ->filter( + fn (array $allocation): bool => in_array( + (int) $allocation['id'], + $assignedServerAllocationIds, + true + ) + ) + ->map( + fn (array $allocation): string => + $this->canonicalIp((string) $allocation['ip']) + ) + ->unique() + ->values() + ->all(); + $nodeClaims = $reservedAllocationClaims[$nodeId] ?? [ + 'ids' => [], + 'ips' => [], + 'blocked_ips' => [], + ]; + $blockedAllocationIds = [ + ...$nodeClaims['ids'], + ...$assignedServerAllocationIds, + ]; + $availableAllocations = array_values(array_map( + fn (array $allocation): array => [ + ...$allocation, + 'ip_in_use' => (bool) ( + $allocation['ip_in_use'] ?? false + ) || in_array( + $this->canonicalIp((string) $allocation['ip']), + $nodeClaims['ips'], + true + ) || in_array( + $this->canonicalIp((string) $allocation['ip']), + $assignedServerIps, + true + ), + ], + array_filter( + $inventoryAllocations, + fn (array $allocation): bool => + ! in_array( + (int) $allocation['id'], + $blockedAllocationIds, + true + ) + && ! in_array( + $this->canonicalIp((string) $allocation['ip']), + $nodeClaims['blocked_ips'], + true + ) + ) + )); + $nodeAvailability = $this->buildNodeAvailability( + $node, + $nodeServers, + $reservations[$nodeId] ?? $this->emptyResources(), + $availableAllocations, + $policies[(string) $node['uuid']] ?? null + ); - $serversByNode = []; - $serverIds = []; - foreach ($serversData as $server) { - $attributes = $this->requireServerAttributes($server); - $nodeId = $attributes['node']; - if (! array_key_exists($nodeId, $nodesById)) { - throw new \RuntimeException('Pterodactyl API returned a server for an unknown included node.'); + $location['nodes'][] = $nodeAvailability; + + foreach (['memory', 'cpu', 'disk'] as $resource) { + $location['total_capacity'][$resource] += $nodeAvailability['total'][$resource]; + $location['total_allocated'][$resource] += $nodeAvailability['allocated'][$resource]; + $location['total_available'][$resource] += $nodeAvailability['available'][$resource]; + + if ($nodeAvailability['eligible']) { + $location['max_available'][$resource] = max( + $location['max_available'][$resource], + $nodeAvailability['available'][$resource] + ); + } } - $this->rememberUniqueId($serverIds, $attributes['id'], 'included server'); - $serversByNode[$nodeId][] = $attributes; - } - $nodes = []; - foreach ($nodesById as $nodeId => $attributes) { - $nodes[] = [ - 'node' => $attributes, - 'servers' => $serversByNode[$nodeId] ?? [], - ]; + if (! $nodeAvailability['cpu_capacity_enforced']) { + $location['cpu_capacity_enforced'] = false; + } } - return $nodes; + return $location; } - private function buildNodeAvailabilityFromServers(array $node, array $servers, array $pendingReservations): array - { - $this->validateNodeAttributes($node); - - $allocated = ['memory' => 0, 'cpu' => 0, 'disk' => 0]; - foreach ($servers as $server) { - $this->validateServerAttributes($server); - $allocated['memory'] += $server['limits']['memory']; - $allocated['cpu'] += $server['limits']['cpu']; - $allocated['disk'] += $server['limits']['disk']; - } - - $effectiveMemory = $node['memory'] * (1 + ($node['memory_overallocate'] ?? 0) / 100); - $effectiveDisk = $node['disk'] * (1 + ($node['disk_overallocate'] ?? 0) / 100); + /** + * @param list, + * allocation_headroom: int + * }> $servers + * @param array{memory: int, cpu: int, disk: int} $reserved + * @param list $availableAllocations + * @return array + */ + private function buildNodeAvailability( + array $node, + array $servers, + array $reserved, + array $availableAllocations, + ?NodeCapacityPolicy $cpuPolicy + ): array { + $memoryOverallocate = (int) $node['memory_overallocate']; + $diskOverallocate = (int) $node['disk_overallocate']; + $totalMemory = $this->effectiveCapacity( + (int) $node['memory'], + $memoryOverallocate + ); + $totalDisk = $this->effectiveCapacity( + (int) $node['disk'], + $diskOverallocate + ); + $cpuPolicyIdentityMatches = $cpuPolicy !== null + && (int) $cpuPolicy->node_id === (int) $node['id'] + && (int) $cpuPolicy->location_id + === (int) $node['location_id']; + $totalCpu = $cpuPolicyIdentityMatches + ? $cpuPolicy->effectiveCpuCapacity() + : 0; + $serverAllocatedMemory = $this->sumServerResource($servers, 'memory'); + $allocatedCpu = $this->sumServerResource($servers, 'cpu'); + $serverAllocatedDisk = $this->sumServerResource($servers, 'disk'); + + $allocated = [ + 'memory' => max( + (int) $node['allocated_resources']['memory'], + $serverAllocatedMemory + ), + 'cpu' => $allocatedCpu, + 'disk' => max( + (int) $node['allocated_resources']['disk'], + $serverAllocatedDisk + ), + ]; $available = [ - 'memory' => max(0, (int) $effectiveMemory - $allocated['memory'] - $pendingReservations['memory']), - 'cpu' => null, - 'disk' => max(0, (int) $effectiveDisk - $allocated['disk'] - $pendingReservations['disk']), + 'memory' => max(0, $totalMemory - $allocated['memory'] - $reserved['memory']), + 'cpu' => max(0, $totalCpu - $allocated['cpu'] - $reserved['cpu']), + 'disk' => max(0, $totalDisk - $allocated['disk'] - $reserved['disk']), ]; + $reasons = []; + if ($node['public'] !== true) { + $reasons[] = 'private_node'; + } + if ($node['maintenance_mode'] === true) { + $reasons[] = 'maintenance_mode'; + } + if ($memoryOverallocate < 0) { + // Pterodactyl uses -1 to disable its memory allocation limit. + // An unbounded panel cannot provide authoritative finite stock. + $reasons[] = 'unbounded_memory_overallocation'; + } + if ($diskOverallocate < 0) { + // Pterodactyl uses -1 to disable its disk allocation limit. + // An unbounded panel cannot provide authoritative finite stock. + $reasons[] = 'unbounded_disk_overallocation'; + } + if ($cpuPolicy !== null && ! $cpuPolicyIdentityMatches) { + $reasons[] = 'cpu_policy_identity_mismatch'; + } elseif ( + $cpuPolicy === null + || ! $cpuPolicy->enabled + || $totalCpu <= 0 + ) { + $reasons[] = 'cpu_policy_missing'; + } + if (collect($servers)->contains( + fn (array $server): bool => (int) $server['memory'] <= 0 + || (int) $server['cpu'] <= 0 + || (int) $server['disk'] <= 0 + )) { + $reasons[] = 'unlimited_existing_resource'; + } + if (collect($servers)->contains( + fn (array $server): bool => (int) ( + $server['allocation_limit'] ?? 0 + ) > 1 + )) { + // In Pterodactyl 1.11, a customer can delete any non-primary + // allocation whenever allocation_limit is nonzero, then add a + // replacement once the assigned count falls below that limit. + // A limit above one can therefore consume a port that Paymenter + // promised to an unpaid seven-day commitment even when the server + // initially has no allocation headroom. Dynamic servers use zero; + // a legacy primary-only server with a total limit of one is safe. + $reasons[] = 'customer_allocation_headroom'; + } + if ($availableAllocations === []) { + $reasons[] = 'no_available_allocation'; + } + return [ - 'node_id' => $node['id'], - 'name' => $node['name'], - 'fqdn' => $node['fqdn'], - 'maintenance_mode' => $node['maintenance_mode'] ?? false, + 'node_id' => (int) $node['id'], + 'node_uuid' => (string) $node['uuid'], + 'name' => (string) $node['name'], + 'fqdn' => (string) $node['fqdn'], + 'public' => (bool) $node['public'], + 'maintenance_mode' => (bool) $node['maintenance_mode'], + 'eligible' => $reasons === [], + 'ineligible_reasons' => $reasons, 'total' => [ - 'memory' => (int) $effectiveMemory, - 'cpu' => null, - 'disk' => (int) $effectiveDisk, + 'memory' => $totalMemory, + 'cpu' => $totalCpu, + 'disk' => $totalDisk, ], 'allocated' => $allocated, - 'reserved' => $pendingReservations, + 'reserved' => $reserved, 'available' => $available, + 'available_allocations' => $availableAllocations, 'server_count' => count($servers), - 'cpu_capacity_enforced' => false, + 'servers' => $servers, + 'cpu_capacity_enforced' => $cpuPolicy !== null + && $cpuPolicyIdentityMatches + && $cpuPolicy->enabled + && $totalCpu > 0 + && ! collect($servers)->contains( + fn (array $server): bool => (int) $server['cpu'] <= 0 + ), 'utilization' => [ - 'memory' => $effectiveMemory > 0 - ? round(($allocated['memory'] + $pendingReservations['memory']) / $effectiveMemory * 100, 1) - : 100, - 'disk' => $effectiveDisk > 0 - ? round(($allocated['disk'] + $pendingReservations['disk']) / $effectiveDisk * 100, 1) - : 100, + 'memory' => $this->utilization( + $allocated['memory'] + $reserved['memory'], + $totalMemory + ), + 'cpu' => $this->utilization( + $allocated['cpu'] + $reserved['cpu'], + $totalCpu + ), + 'disk' => $this->utilization( + $allocated['disk'] + $reserved['disk'], + $totalDisk + ), ], ]; } - private function fetchAllLocations(): array + private function effectiveCapacity(int $physical, int $overallocatePercent): int { - $locations = []; - $locationIds = []; - foreach ($this->pterodactylGetPaginatedData('/api/application/locations', ['per_page' => 100]) as $location) { - $attributes = $this->requireLocationAttributes($location); - $this->rememberUniqueId($locationIds, $attributes['id'], 'location'); - $locations[] = [ - 'id' => $attributes['id'], - 'short' => $attributes['short'], - 'long' => $attributes['long'], - ]; + if ($overallocatePercent < 0) { + // Keep diagnostics finite while the ineligibility reason above + // prevents this node from participating in quotes or placement. + return max(0, $physical); } - return $locations; - } - - private function fetchClusterNodes(): array - { - try { - return $this->fetchClusterNodesWithIncludedServers(); - } catch (\RuntimeException $exception) { - if ($this->shouldReturnDegradedSnapshot($exception)) { - throw $exception; - } - - if ($exception->getMessage() !== 'Pterodactyl API returned a missing servers relationship payload.') { - throw $exception; - } - - return $this->fetchClusterNodesFromServerIndex(); + if ($overallocatePercent > PHP_INT_MAX - 100) { + throw new \RuntimeException('Pterodactyl overallocation value is outside the supported range.'); } - } - - private function fetchClusterNodesWithIncludedServers(): array - { - $nodes = []; - $serverIds = []; - foreach ($this->pterodactylGetPaginatedData('/api/application/nodes', [ - 'include' => 'servers', - 'per_page' => 100, - ]) as $node) { - $attributes = $this->requireNodeAttributes($node); - $this->rememberUniqueId($nodes, $attributes['id'], 'node'); - $servers = []; - foreach ($this->requireRelationshipData($node, 'servers') as $server) { - $serverAttributes = $this->requireServerAttributes($server); - if ($serverAttributes['node'] !== $attributes['id']) { - throw new \RuntimeException('Pterodactyl API returned a server for an unexpected node.'); - } - $this->rememberUniqueId($serverIds, $serverAttributes['id'], 'server'); - $servers[] = $serverAttributes; - } - $nodes[$attributes['id']] = [ - 'node' => $attributes, - 'location_id' => $attributes['location_id'], - 'servers' => $servers, - ]; + $factor = max(0, 100 + $overallocatePercent); + if ($factor > 0 && $physical > intdiv(PHP_INT_MAX, $factor)) { + throw new \RuntimeException('Pterodactyl effective capacity exceeds the supported range.'); } - return $nodes; + return max(0, intdiv($physical * $factor, 100)); } - private function fetchClusterNodesFromServerIndex(): array + private function utilization(int $used, int $total): float { - $nodes = []; - foreach ($this->pterodactylGetPaginatedData('/api/application/nodes', ['per_page' => 100]) as $node) { - $attributes = $this->requireNodeAttributes($node); - $this->rememberUniqueId($nodes, $attributes['id'], 'node'); - $nodes[$attributes['id']] = [ - 'node' => $attributes, - 'location_id' => $attributes['location_id'], - 'servers' => [], - ]; - } - - $serverIds = []; - foreach ($this->pterodactylGetPaginatedData('/api/application/servers', ['per_page' => 100]) as $server) { - $attributes = $this->requireServerAttributes($server); - $nodeId = $attributes['node']; - - if (! array_key_exists($nodeId, $nodes)) { - throw new \RuntimeException('Pterodactyl API returned a server for an unknown node.'); - } - - $this->rememberUniqueId($serverIds, $attributes['id'], 'server'); - $nodes[$nodeId]['servers'][] = $attributes; - } - - return $nodes; + return $total > 0 ? round($used / $total * 100, 1) : 100.0; } - private function pterodactylGetPaginatedData(string $path, array $query = []): array + /** + * @param list> $servers + */ + private function sumServerResource(array $servers, string $resource): int { - $page = 1; - $data = []; - $expectedTotalPages = null; - $expectedPerPage = null; - $expectedTotal = null; - - while (true) { - $payload = $this->pterodactylGet($path, array_merge($query, ['page' => $page])); - if (! is_array($payload['data'] ?? null)) { - throw new \RuntimeException('Pterodactyl API returned an invalid paginated data payload.'); - } - $pageData = $payload['data']; - - $pagination = $payload['meta']['pagination'] ?? null; - if (! is_array($pagination)) { - throw new \RuntimeException('Pterodactyl API returned invalid pagination metadata.'); - } - - $currentPage = filter_var( - $pagination['current_page'] ?? null, - FILTER_VALIDATE_INT, - ['options' => ['min_range' => 1]], - ); - $totalPages = filter_var( - $pagination['total_pages'] ?? null, - FILTER_VALIDATE_INT, - ['options' => ['min_range' => 1]], - ); - $count = filter_var( - $pagination['count'] ?? null, - FILTER_VALIDATE_INT, - ['options' => ['min_range' => 0]], - ); - $perPage = filter_var( - $pagination['per_page'] ?? null, - FILTER_VALIDATE_INT, - ['options' => ['min_range' => 1]], - ); - $total = filter_var( - $pagination['total'] ?? null, - FILTER_VALIDATE_INT, - ['options' => ['min_range' => 0]], - ); - if ($currentPage === false || $totalPages === false || $count === false - || $perPage === false || $total === false - || $currentPage !== $page || $totalPages < $currentPage) { - throw new \RuntimeException('Pterodactyl API returned invalid pagination metadata.'); - } + $sum = 0; - $expectedTotalPages ??= $totalPages; - $expectedPerPage ??= $perPage; - $expectedTotal ??= $total; - if ($totalPages !== $expectedTotalPages || $perPage !== $expectedPerPage || $total !== $expectedTotal) { - throw new \RuntimeException('Pterodactyl API returned inconsistent pagination metadata.'); - } - - $calculatedTotalPages = max(1, (int) ceil($total / $perPage)); - $expectedCount = $currentPage < $totalPages - ? $perPage - : max(0, $total - ($perPage * ($currentPage - 1))); - if ($totalPages !== $calculatedTotalPages || $count !== count($pageData) || $count !== $expectedCount) { - throw new \RuntimeException('Pterodactyl API returned incomplete pagination data.'); - } - - $data = array_merge($data, $pageData); - if ($currentPage === $totalPages) { - break; + foreach ($servers as $server) { + $value = (int) ($server[$resource] ?? 0); + if ($value < 0 || $value > PHP_INT_MAX - $sum) { + throw new \RuntimeException( + "Pterodactyl {$resource} allocation exceeds the supported range." + ); } - - $page = $currentPage + 1; + $sum += $value; } - if (count($data) !== $expectedTotal) { - throw new \RuntimeException('Pterodactyl API returned incomplete pagination data.'); - } - - return $data; + return $sum; } - private function requireLocationAttributes(mixed $payload): array + /** + * @param list> $nodes + * @return array + */ + private function cpuPolicies(array $nodes): array { - $attributes = is_array($payload) && is_array($payload['attributes'] ?? null) - ? $payload['attributes'] - : null; - if ($attributes === null - || filter_var($attributes['id'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) === false - || ! is_string($attributes['short'] ?? null) || $attributes['short'] === '' - || ! is_string($attributes['long'] ?? null) || $attributes['long'] === '') { - throw new \RuntimeException('Pterodactyl API returned an invalid location payload.'); - } + $uuids = array_values(array_map( + fn (array $node): string => (string) $node['uuid'], + $nodes + )); - $attributes['id'] = (int) $attributes['id']; + if ($uuids === []) { + return []; + } - return $attributes; + return NodeCapacityPolicy::query() + ->forPanel($this->inventory->panelIdentity()) + ->whereIn('node_uuid', $uuids) + ->get() + ->keyBy('node_uuid') + ->all(); } - private function requireRelationshipData(array $payload, string $relationship): array - { - $attributes = is_array($payload['attributes'] ?? null) ? $payload['attributes'] : []; - if (! array_key_exists('relationships', $attributes)) { - throw new \RuntimeException(sprintf( - 'Pterodactyl API returned a missing %s relationship payload.', - $relationship - )); - } - - $relationships = $attributes['relationships']; - if (! is_array($relationships)) { - throw new \RuntimeException(sprintf( - 'Pterodactyl API returned an invalid %s relationship payload.', - $relationship - )); + /** + * @param list $nodeIds + * Confirmed commitments remain in the local overlay until the independently + * read server snapshot proves the exact target vector. This closes the + * handoff window where the local row is consumed before every Pterodactyl + * inventory endpoint reflects the create or update. + * + * @param array>> $servers + * @return array + */ + private function holdingReservations( + array $nodeIds, + array $servers, + ?string $excludeReservationToken + ): array { + if ($nodeIds === []) { + return []; } - if (! array_key_exists($relationship, $relationships)) { - throw new \RuntimeException(sprintf( - 'Pterodactyl API returned a missing %s relationship payload.', - $relationship - )); - } + $query = DB::table('ptero_resource_reservations as reservations') + ->leftJoin( + 'services', + 'services.id', + '=', + 'reservations.service_id' + ) + ->where( + 'reservations.panel_identity', + $this->inventory->panelIdentity() + ) + ->whereIn('reservations.node_id', $nodeIds) + ->where(function ($query): void { + $query->where(function ($query): void { + $query->where( + 'reservations.status', + ResourceReservation::STATUS_PENDING + )->where('reservations.expires_at', '>', now()); + })->orWhere( + 'reservations.status', + ResourceReservation::STATUS_PAID_COMMITTED + )->orWhere(function ($query): void { + $query->where( + 'reservations.status', + ResourceReservation::STATUS_CONFIRMED + )->where(function ($query): void { + $query->whereNull('services.status') + ->orWhere('services.status', '!=', 'cancelled'); + }); + }); + }); - $entry = $relationships[$relationship]; - if (! is_array($entry) || ! is_array($entry['data'] ?? null)) { - throw new \RuntimeException(sprintf( - 'Pterodactyl API returned an invalid %s relationship payload.', - $relationship - )); + if ($excludeReservationToken !== null) { + $query->where( + 'reservations.token', + '!=', + $excludeReservationToken + ); } - return $entry['data']; - } + $rows = $query->get([ + 'reservations.id', + 'reservations.node_id', + 'reservations.service_id', + 'reservations.service_upgrade_id', + 'reservations.purpose', + 'reservations.status', + 'reservations.external_server_id', + 'reservations.external_server_uuid', + 'reservations.external_server_identifier', + 'reservations.configuration_payload', + 'reservations.memory', + 'reservations.cpu', + 'reservations.disk', + 'reservations.reserved_memory', + 'reservations.reserved_cpu', + 'reservations.reserved_disk', + 'reservations.consumed_at', + 'reservations.created_at', + 'reservations.updated_at', + ]); + + $totals = []; + $confirmedByService = []; + + foreach ($rows as $reservation) { + if ($reservation->status === ResourceReservation::STATUS_CONFIRMED) { + $key = $reservation->service_id === null + ? 'reservation:'.(int) $reservation->id + : 'service:'.(int) $reservation->service_id; + $confirmedByService[$key][] = $reservation; + + continue; + } - private function requireNodeAttributes(mixed $payload): array - { - $attributes = is_array($payload) && is_array($payload['attributes'] ?? null) - ? $payload['attributes'] - : null; - if ($attributes === null) { - throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); + $nodeId = (int) $reservation->node_id; + $isUpgrade = $reservation->purpose === 'upgrade'; + $this->addReservedResources($totals, $nodeId, [ + 'memory' => (int) ( + $isUpgrade + ? $reservation->reserved_memory + : $reservation->memory + ), + 'cpu' => (int) ( + $isUpgrade + ? $reservation->reserved_cpu + : $reservation->cpu + ), + 'disk' => (int) ( + $isUpgrade + ? $reservation->reserved_disk + : $reservation->disk + ), + ]); } - $this->validateNodeAttributes($attributes); - $attributes['id'] = (int) $attributes['id']; - $attributes['location_id'] = (int) $attributes['location_id']; - foreach (['memory', 'disk', 'cpu_threads'] as $field) { - $attributes[$field] = (int) $attributes[$field]; - } - foreach (['memory_overallocate', 'disk_overallocate'] as $field) { - if (array_key_exists($field, $attributes)) { - $attributes[$field] = (int) $attributes[$field]; - } + foreach ($confirmedByService as $expectations) { + $target = $this->latestConfirmedTarget($expectations); + $nodeId = (int) $target->node_id; + $this->addReservedResources( + $totals, + $nodeId, + $this->confirmedExpectationOverlay( + $target, + $expectations, + $servers[$nodeId] ?? [] + ) + ); } - return $attributes; + return $totals; } - private function requireServerAttributes(mixed $payload): array + /** + * A completed upgrade supersedes the checkout vector and every older + * upgrade for the same service. Completion time is authoritative; the + * immutable row ID breaks a same-timestamp tie. + * + * @param list $expectations + */ + private function latestConfirmedTarget(array $expectations): object { - $attributes = is_array($payload) && is_array($payload['attributes'] ?? null) - ? $payload['attributes'] - : null; - if ($attributes === null) { - throw new \RuntimeException('Pterodactyl API returned an invalid included server payload.'); - } - - $this->validateServerAttributes($attributes); - $attributes['id'] = (int) $attributes['id']; - $attributes['node'] = (int) $attributes['node']; - foreach (['memory', 'cpu', 'disk'] as $field) { - $attributes['limits'][$field] = (int) $attributes['limits'][$field]; - } - - return $attributes; + $upgrades = array_values(array_filter( + $expectations, + fn (object $row): bool => $row->purpose === 'upgrade' + )); + $candidates = $upgrades === [] ? $expectations : $upgrades; + + usort($candidates, function (object $left, object $right): int { + $leftTime = strtotime((string) ( + $left->consumed_at + ?? $left->updated_at + ?? $left->created_at + ?? '' + )) ?: 0; + $rightTime = strtotime((string) ( + $right->consumed_at + ?? $right->updated_at + ?? $right->created_at + ?? '' + )) ?: 0; + + return [$leftTime, (int) $left->id] + <=> [$rightTime, (int) $right->id]; + }); + + return $candidates[array_key_last($candidates)]; } - private function validateNodeAttributes(array $attributes): void - { - foreach (['id', 'location_id'] as $field) { - if (filter_var($attributes[$field] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) === false) { - throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); - } + /** + * The same server-list snapshot used by aggregate allocation must prove + * the pinned identity, node, and complete target vector. If a resize is + * visible but still converging, only the positive component deficit is + * overlaid. If identity is absent or ambiguous, the full target stays held. + * + * @param list $expectations + * @param list> $servers + * @return array{memory: int, cpu: int, disk: int} + */ + private function confirmedExpectationOverlay( + object $target, + array $expectations, + array $servers + ): array { + $identity = $this->confirmedExternalIdentity($expectations); + if ($identity['ambiguous'] || $identity['id'] <= 0) { + return $this->targetResources($target); } - foreach (['memory', 'disk', 'cpu_threads'] as $field) { - if (! is_int($attributes[$field] ?? null) || $attributes[$field] < 1) { - throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); + $matches = array_values(array_filter( + $servers, + function (array $server) use ($identity, $target): bool { + return (int) ($server['id'] ?? 0) === $identity['id'] + && ( + $identity['uuid'] === null + || ($server['uuid'] ?? null) === $identity['uuid'] + ) + && ( + $identity['identifier'] === null + || ($server['identifier'] ?? null) + === $identity['identifier'] + ) + && ( + array_key_exists('external_id', $server) + && (string) ($server['external_id'] ?? '') + === (string) ($target->service_id ?? '') + ); } + )); + if (count($matches) !== 1) { + return $this->targetResources($target); } - if (! is_string($attributes['name'] ?? null) || $attributes['name'] === '' - || ! is_string($attributes['fqdn'] ?? null) || $attributes['fqdn'] === '') { - throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); + $overlay = []; + foreach (['memory', 'cpu', 'disk'] as $resource) { + $overlay[$resource] = max( + 0, + (int) $target->{$resource} + - (int) ($matches[0][$resource] ?? 0) + ); } - foreach (['memory_overallocate', 'disk_overallocate'] as $field) { - if (array_key_exists($field, $attributes) && ! is_int($attributes[$field])) { - throw new \RuntimeException('Pterodactyl API returned an invalid included node payload.'); - } - } + return $overlay; } - private function validateServerAttributes(array $attributes): void - { - if (filter_var($attributes['id'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) === false - || filter_var($attributes['node'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) === false - || ! is_array($attributes['limits'] ?? null)) { - throw new \RuntimeException('Pterodactyl API returned an invalid included server payload.'); - } - - foreach (['memory', 'cpu', 'disk'] as $field) { - if (! is_int($attributes['limits'][$field] ?? null) || $attributes['limits'][$field] < 0) { - throw new \RuntimeException('Pterodactyl API returned an invalid included server payload.'); + /** + * @param list $expectations + * @return array{ + * id: int, + * uuid: ?string, + * identifier: ?string, + * ambiguous: bool + * } + */ + private function confirmedExternalIdentity( + array $expectations + ): array { + $ids = []; + $uuids = []; + $identifiers = []; + + foreach ($expectations as $expectation) { + $payload = is_array($expectation->configuration_payload ?? null) + ? $expectation->configuration_payload + : json_decode( + (string) ($expectation->configuration_payload ?? ''), + true + ); + $id = (int) ( + $expectation->external_server_id + ?? (is_array($payload) + ? ($payload['external_server_id'] ?? 0) + : 0) + ); + if ($id > 0) { + $ids[$id] = true; + } + $uuid = $this->optionalIdentityString( + $expectation->external_server_uuid ?? null + ); + if ($uuid !== null) { + $uuids[$uuid] = true; + } + $identifier = $this->optionalIdentityString( + $expectation->external_server_identifier ?? null + ); + if ($identifier !== null) { + $identifiers[$identifier] = true; } } - } - - private function rememberUniqueId(array &$seen, int $id, string $resource): void - { - if (array_key_exists($id, $seen)) { - throw new \RuntimeException("Pterodactyl API returned a duplicate {$resource}."); - } - - $seen[$id] = true; - } - private function emptyClusterSnapshot(): array - { return [ - 'locations' => [], - 'nodes' => [], - 'by_location' => [], - 'generated_at' => \now()->toIso8601String(), + 'id' => count($ids) === 1 ? (int) array_key_first($ids) : 0, + 'uuid' => count($uuids) === 1 + ? (string) array_key_first($uuids) + : null, + 'identifier' => count($identifiers) === 1 + ? (string) array_key_first($identifiers) + : null, + 'ambiguous' => count($ids) > 1 + || count($uuids) > 1 + || count($identifiers) > 1, ]; } - private function degradedClusterSnapshot(): array + private function optionalIdentityString(mixed $value): ?string { - return $this->emptyClusterSnapshot() + [ - 'error' => 'Pterodactyl unavailable', - ]; + return is_string($value) && trim($value) !== '' + ? trim($value) + : null; } - private function shouldReturnDegradedSnapshot(\Throwable $exception): bool + /** + * @return array{memory: int, cpu: int, disk: int} + */ + private function targetResources(object $target): array { - if ($this->extractStatusCode($exception) >= 500) { - return true; - } - - return str_contains($exception->getMessage(), 'Pterodactyl API connection failed'); + return [ + 'memory' => (int) $target->memory, + 'cpu' => (int) $target->cpu, + 'disk' => (int) $target->disk, + ]; } - private function extractStatusCode(\Throwable $exception): int - { - preg_match('/\((\d{3})\)/', $exception->getMessage(), $matches); - - return (int) ($matches[1] ?? 0); + /** + * @param array $totals + * @param array{memory: int, cpu: int, disk: int} $resources + */ + private function addReservedResources( + array &$totals, + int $nodeId, + array $resources + ): void { + $totals[$nodeId] ??= $this->emptyResources(); + + foreach ($resources as $resource => $value) { + if ( + $value < 0 + || $value > PHP_INT_MAX - $totals[$nodeId][$resource] + ) { + throw new \RuntimeException( + "Reserved {$resource} exceeds the supported range." + ); + } + $totals[$nodeId][$resource] += $value; + } } - private function getPendingReservationsForNodes(array $nodeIds): array - { + /** + * @param list $nodeIds + * @return array, + * ips: list, + * blocked_ips: list + * }> + */ + private function reservedAllocationClaims( + array $nodeIds, + ?string $excludeReservationToken + ): array { if ($nodeIds === []) { return []; } - return DB::table('ptero_resource_reservations') - ->whereIn('node_id', $nodeIds) - ->where('status', 'pending') - ->where('expires_at', '>', \now()) - ->select('node_id') - ->selectRaw('COALESCE(SUM(memory), 0) as memory') - ->selectRaw('COALESCE(SUM(cpu), 0) as cpu') - ->selectRaw('COALESCE(SUM(disk), 0) as disk') - ->groupBy('node_id') - ->get() - ->mapWithKeys(fn ($reservation) => [ - $reservation->node_id => [ - 'memory' => (int) $reservation->memory, - 'cpu' => (int) $reservation->cpu, - 'disk' => (int) $reservation->disk, - ], - ]) - ->toArray(); - } - - private function pterodactylGet(string $path, array $query = []): array - { - try { - $response = Http::withHeaders([ - 'Authorization' => 'Bearer '.$this->apiKey, - 'Accept' => 'application/json', - ]) - ->timeout(3) // per-attempt; worst case: 2 × 3s + 250ms = ~6.25s - ->connectTimeout(2) - ->retry(2, 250, function ($exception) { - // Per-attempt timeout, not end-to-end. Retry on connection errors only. - // Do not retry 4xx (other than 429) or 5xx — Pterodactyl returns meaningful errors. - return $exception instanceof ConnectionException; - }, throw: false) - ->get($this->apiUrl.$path, $query); - } catch (ConnectionException $exception) { - // Full message may contain internal hostnames/ports; log for diagnostics, throw sanitized. - \report($exception); - throw new \RuntimeException('Pterodactyl API connection failed.', previous: $exception); - } + $query = DB::table('ptero_reservation_allocations as allocations') + ->join( + 'ptero_resource_reservations as reservations', + 'reservations.id', + '=', + 'allocations.reservation_id' + ) + ->leftJoin( + 'services', + 'services.id', + '=', + 'reservations.service_id' + ) + ->where( + 'reservations.panel_identity', + $this->inventory->panelIdentity() + ) + ->whereColumn( + 'allocations.panel_identity', + 'reservations.panel_identity' + ) + ->whereIn('allocations.node_id', $nodeIds) + ->where(function ($query): void { + $query->where(function ($query): void { + $query->whereNull('allocations.released_at') + ->where(function ($query): void { + $query->where(function ($query): void { + $query->where( + 'reservations.status', + ResourceReservation::STATUS_PENDING + )->where( + 'reservations.expires_at', + '>', + now() + ); + })->orWhere( + 'reservations.status', + ResourceReservation::STATUS_PAID_COMMITTED + ); + }); + })->orWhere(function ($query): void { + $query->where( + 'reservations.status', + ResourceReservation::STATUS_CONFIRMED + )->where(function ($query): void { + $query->whereNull('services.status') + ->orWhere( + 'services.status', + '!=', + 'cancelled' + ); + }); + }); + }); - if ($response->status() === 429) { - throw new \RuntimeException('Pterodactyl rate limit exceeded. Retry in a few seconds.'); - } - if ($response->failed()) { - // Log full upstream body for diagnostics, but do NOT leak it to callers — - // AvailabilityController surfaces exception messages to API clients. - \report(new \RuntimeException(sprintf( - 'Pterodactyl API error (%d) body: %s', - $response->status(), - $response->body() - ))); - - throw new \RuntimeException(sprintf('Pterodactyl API error (%d).', $response->status())); + if ($excludeReservationToken !== null) { + $query->where('reservations.token', '!=', $excludeReservationToken); } - $payload = $response->json(); - - if (! is_array($payload)) { - throw new \RuntimeException(sprintf( - 'Pterodactyl API returned an invalid JSON payload (status %d).', - $response->status() - )); - } + return $query + ->get([ + 'allocations.node_id', + 'allocations.allocation_id', + 'allocations.ip', + 'allocations.released_at', + 'reservations.status', + 'reservations.configuration_payload', + 'services.status as service_status', + ]) + ->groupBy('node_id') + ->map(function ($rows): array { + $holdingOrActive = $rows->filter( + fn ($row): bool => in_array( + $row->status, + [ + ResourceReservation::STATUS_PENDING, + ResourceReservation::STATUS_PAID_COMMITTED, + ResourceReservation::STATUS_CONFIRMED, + ], + true + ) + ); + $dedicated = $rows->filter(function ($row): bool { + $payload = json_decode( + (string) $row->configuration_payload, + true + ); + + return is_array($payload) + && data_get( + $payload, + 'allocation_requirements.dedicated_ip' + ) === true; + }); - return $payload; + return [ + 'ids' => $holdingOrActive + ->pluck('allocation_id') + ->map(fn ($id): int => (int) $id) + ->unique() + ->values() + ->all(), + 'ips' => $holdingOrActive + ->pluck('ip') + ->filter(fn ($ip): bool => is_string($ip) && $ip !== '') + ->map(fn (string $ip): string => $this->canonicalIp($ip)) + ->unique() + ->values() + ->all(), + 'blocked_ips' => $dedicated + ->pluck('ip') + ->filter( + fn ($ip): bool => is_string($ip) && $ip !== '' + ) + ->map( + fn (string $ip): string => + $this->canonicalIp($ip) + ) + ->unique() + ->values() + ->all(), + ]; + }) + ->all(); } - private function getPendingReservations(int $nodeId, ?string $excludeReservationToken = null): array + private function canonicalIp(string $ip): string { - $query = DB::table('ptero_resource_reservations') - ->where('node_id', $nodeId) - ->where('status', 'pending') - ->where('expires_at', '>', \now()); + $packed = @inet_pton(trim($ip)); - if ($excludeReservationToken !== null) { - $query->where('token', '!=', $excludeReservationToken); - } + return $packed === false + ? strtolower(trim($ip)) + : bin2hex($packed); + } - $result = $query - ->selectRaw('COALESCE(SUM(memory), 0) as memory') - ->selectRaw('COALESCE(SUM(cpu), 0) as cpu') - ->selectRaw('COALESCE(SUM(disk), 0) as disk') - ->first(); + /** + * @return array{memory: int, cpu: int, disk: int} + */ + private function emptyResources(): array + { + return ['memory' => 0, 'cpu' => 0, 'disk' => 0]; + } + private function emptyClusterSnapshot(): array + { return [ - 'memory' => (int) $result->memory, - 'cpu' => (int) $result->cpu, - 'disk' => (int) $result->disk, + 'locations' => [], + 'nodes' => [], + 'by_location' => [], + 'generated_at' => now()->toIso8601String(), ]; } - private function getNodeLocation(int $nodeId): int + private function degradedClusterSnapshot(): array { - $data = $this->pterodactylGet("/api/application/nodes/{$nodeId}"); - - $locationId = $data['attributes']['location_id'] ?? null; - if (! is_int($locationId)) { - throw new \RuntimeException("Pterodactyl node {$nodeId} response is missing location_id."); - } - - return $locationId; + return $this->emptyClusterSnapshot() + ['error' => 'Pterodactyl unavailable']; } - private function getExtensionConfig(): array + private function shouldReturnDegradedSnapshot(\Throwable $exception): bool { - return Extension::where('extension', 'DynamicPterodactyl') - ->where('enabled', true) - ->first() - ?->settings - ->pluck('value', 'key') - ->toArray() ?? []; + return str_contains($exception->getMessage(), 'connection failed') + || preg_match('/inventory API error \\(5\\d\\d\\)/', $exception->getMessage()) === 1; } } diff --git a/Services/ResourceQuoteService.php b/Services/ResourceQuoteService.php new file mode 100644 index 0000000..c78c0b2 --- /dev/null +++ b/Services/ResourceQuoteService.php @@ -0,0 +1,270 @@ + $submittedOptions + * @return array{ + * available: true, + * adjusted: bool, + * selection: array{memory: int, cpu: int, disk: int}, + * bounds: array + * } + */ + public function quote( + Product $product, + array $submittedOptions, + ?string $excludeReservationToken = null + ): array { + $configuration = $this->configuration->forQuote($product, $submittedOptions); + $availability = $this->resources->getLocationAvailability( + $configuration['location_id'], + $excludeReservationToken + ); + $nodes = array_values(array_filter( + $availability['nodes'], + fn (array $node): bool => ($node['eligible'] ?? false) + && $this->allocations->select( + $node['available_allocations'] ?? [], + $configuration['allocation_count'], + $configuration['required_ports'] ?? [], + $configuration['allowed_port_ranges'] ?? [], + (bool) ($configuration['dedicated_ip'] ?? false) + ) !== null + )); + + if ( + $nodes === [] + && collect($availability['nodes'])->contains( + fn (array $node): bool => array_intersect( + $node['ineligible_reasons'] ?? [], + [ + 'cpu_policy_missing', + 'unlimited_existing_resource', + 'unbounded_memory_overallocation', + 'unbounded_disk_overallocation', + ] + ) !== [] + ) + ) { + throw new InvalidStockConfigurationException( + 'Eligible nodes are missing authoritative bounded resource inventory.' + ); + } + + if ($nodes === []) { + throw new StockUnavailableException( + 'No server currently has the required resource and port capacity.' + ); + } + + $requested = $configuration['resources']; + $selection = $this->vectorFitsAnyNode($requested, $nodes) + ? $requested + : $this->bestAdjustedVector($configuration, $nodes); + + if ($selection === null) { + throw new StockUnavailableException( + 'No server currently has enough stock for this product minimum.' + ); + } + + return [ + 'available' => true, + 'adjusted' => $selection !== $requested, + 'selection' => $selection, + 'bounds' => $this->conditionalBounds( + $configuration['sliders'], + $selection, + $nodes + ), + ]; + } + + /** + * @param array $configuration + * @param list> $nodes + * @return array{memory: int, cpu: int, disk: int}|null + */ + private function bestAdjustedVector(array $configuration, array $nodes): ?array + { + $candidates = []; + + foreach ($nodes as $node) { + $candidate = $configuration['resources']; + $valid = true; + + foreach (['memory', 'cpu', 'disk'] as $resource) { + if (! isset($configuration['sliders'][$resource])) { + if ($candidate[$resource] > $node['available'][$resource]) { + $valid = false; + break; + } + + continue; + } + + $slider = $configuration['sliders'][$resource]; + $nodeMaximum = min( + $slider['max'], + (int) $node['available'][$resource] + ); + $nodeMaximum = $this->snapDown( + $nodeMaximum, + $slider['min'], + $slider['step'] + ); + + if ($nodeMaximum < $slider['min']) { + $valid = false; + break; + } + + $candidate[$resource] = min( + $candidate[$resource], + $nodeMaximum + ); + } + + if (! $valid || ! $this->vectorFitsNode($candidate, $node)) { + continue; + } + + $retention = 0.0; + foreach ($configuration['sliders'] as $resource => $slider) { + $retention += $candidate[$resource] / max(1, $configuration['resources'][$resource]); + } + + $candidates[] = [ + 'selection' => $candidate, + 'retention' => $retention, + 'node_id' => (int) $node['node_id'], + ]; + } + + if ($candidates === []) { + return null; + } + + usort($candidates, function (array $left, array $right): int { + $retention = $right['retention'] <=> $left['retention']; + + return $retention !== 0 + ? $retention + : $left['node_id'] <=> $right['node_id']; + }); + + return $candidates[0]['selection']; + } + + /** + * Each bound is conditional on the other two selected resources. This + * prevents independently advertised maxima from coming from different + * Pterodactyl nodes. + * + * @param array> $sliders + * @param array{memory: int, cpu: int, disk: int} $selection + * @param list> $nodes + * @return array + */ + private function conditionalBounds( + array $sliders, + array $selection, + array $nodes + ): array { + $bounds = []; + + foreach ($sliders as $resource => $slider) { + $maximum = null; + + foreach ($nodes as $node) { + $otherResourcesFit = true; + foreach (['memory', 'cpu', 'disk'] as $otherResource) { + if ($otherResource === $resource) { + continue; + } + + if ($selection[$otherResource] > $node['available'][$otherResource]) { + $otherResourcesFit = false; + break; + } + } + + if (! $otherResourcesFit) { + continue; + } + + $nodeMaximum = $this->snapDown( + min($slider['max'], (int) $node['available'][$resource]), + $slider['min'], + $slider['step'] + ); + if ($nodeMaximum >= $slider['min']) { + $maximum = max($maximum ?? $slider['min'], $nodeMaximum); + } + } + + if ($maximum === null) { + throw new StockUnavailableException( + 'No server can satisfy the complete selected resource combination.' + ); + } + + $bounds[$resource] = [ + 'config_option_id' => $slider['config_option_id'], + 'min' => $slider['min'], + 'max' => $maximum, + 'configured_max' => $slider['max'], + 'step' => $slider['step'], + ]; + } + + return $bounds; + } + + /** + * @param array{memory: int, cpu: int, disk: int} $vector + * @param list> $nodes + */ + private function vectorFitsAnyNode(array $vector, array $nodes): bool + { + return collect($nodes)->contains( + fn (array $node): bool => $this->vectorFitsNode($vector, $node) + ); + } + + /** + * @param array{memory: int, cpu: int, disk: int} $vector + */ + private function vectorFitsNode(array $vector, array $node): bool + { + return $vector['memory'] <= $node['available']['memory'] + && $vector['cpu'] <= $node['available']['cpu'] + && $vector['disk'] <= $node['available']['disk']; + } + + private function snapDown(int $value, int $minimum, int $step): int + { + if ($value < $minimum) { + return $minimum - 1; + } + + return $minimum + intdiv($value - $minimum, $step) * $step; + } +} diff --git a/Services/SliderConfigReaderService.php b/Services/SliderConfigReaderService.php deleted file mode 100644 index c50f470..0000000 --- a/Services/SliderConfigReaderService.php +++ /dev/null @@ -1,68 +0,0 @@ -getDynamicSliderOptions($productId); - - if ($options->isEmpty()) { - return [ - 'has_config' => false, - 'sliders' => [], - ]; - } - - $sliders = []; - - foreach ($options as $option) { - $metadata = $option->metadata; - if (! is_array($metadata)) { - $metadata = json_decode($metadata, true) ?? []; - } - - $resourceType = $metadata['resource_type'] ?? strtolower($option->name); - - $sliders[$resourceType] = [ - 'config_option_id' => $option->id, - 'name' => $option->name, - 'min' => $metadata['min'] ?? 0, - 'max' => $metadata['max'] ?? 0, - 'step' => $metadata['step'] ?? 1, - 'default' => $metadata['default'] ?? $metadata['min'] ?? 0, - 'unit' => $metadata['unit'] ?? '', - 'display_unit' => $metadata['display_unit'] ?? $metadata['unit'] ?? '', - 'display_divisor' => $metadata['display_divisor'] ?? 1, - 'pricing' => $metadata['pricing'] ?? ['model' => 'linear', 'rate_per_unit' => 0], - ]; - } - - return [ - 'has_config' => true, - 'sliders' => $sliders, - ]; - } - - /** - * Get dynamic_slider ConfigOptions for a product - * - * @return \Illuminate\Support\Collection - */ - private function getDynamicSliderOptions(int $productId) - { - return ConfigOption::whereHas('products', fn ($q) => $q->where('product_id', $productId)) - ->where('type', 'dynamic_slider') - ->whereNull('parent_id') - ->get(); - } - -} diff --git a/Services/UpgradeReservationService.php b/Services/UpgradeReservationService.php new file mode 100644 index 0000000..eb53a44 --- /dev/null +++ b/Services/UpgradeReservationService.php @@ -0,0 +1,1654 @@ +inventory->assertExclusiveProvisioningControl(); + $this->assertServiceAcceptsUpgrade($upgrade->service); + $context = $this->upgradeContext($upgrade, requireSourceMatch: true); + $fingerprint = $this->reservationFingerprint($upgrade, $context); + + return DB::transaction(function () use ( + $upgrade, + $guaranteedUntil, + $context, + $fingerprint + ): UpgradeReservation { + $this->lockCapacityScope( + $context['panel_identity'], + $context['location_id'] + ); + + DB::table('ptero_resource_reservations') + ->where('panel_identity', $context['panel_identity']) + ->where('location_id', $context['location_id']) + ->where(function (Builder $query): void { + $query->where(function (Builder $query): void { + $query->where('status', 'pending') + ->where('expires_at', '>', now()); + })->orWhere('status', 'paid_committed'); + }) + ->lockForUpdate() + ->get(); + + $existing = UpgradeReservation::query() + ->where('purpose', 'upgrade') + ->where('service_upgrade_id', $upgrade->id) + ->whereIn('status', ['pending', 'paid_committed']) + ->lockForUpdate() + ->first(); + + if ($existing?->status === 'paid_committed') { + if (! hash_equals( + (string) $existing->configuration_fingerprint, + $fingerprint + )) { + throw new DisplayException( + 'The paid upgrade commitment does not match this configuration.' + ); + } + + return $existing; + } + + $excludeToken = $existing?->token; + if (! $this->resources->verifyNodeCapacity( + $context['node_id'], + $context['delta'], + 0, + $excludeToken + )) { + throw new StockUnavailableException( + 'The current node does not have enough stock for this resource upgrade.' + ); + } + + $payload = [ + 'service_upgrade_id' => (int) $upgrade->id, + 'source_fingerprint' => (string) $upgrade->source_fingerprint, + 'target_fingerprint' => (string) $upgrade->target_fingerprint, + 'panel_identity' => $context['panel_identity'], + 'node_id' => $context['node_id'], + 'location_id' => $context['location_id'], + 'external_server_id' => $context['external_server_id'], + 'external_server_uuid' => $context['external_server_uuid'], + 'external_server_identifier' => + $context['external_server_identifier'], + 'external_server_external_id' => + $context['external_server_external_id'], + 'external_user_id' => $context['external_user_id'], + 'user_external_id' => $context['user_external_id'], + 'user_email' => $context['user_email'], + 'nest_id' => $context['nest_id'], + 'egg_id' => $context['egg_id'], + 'preserved_build' => $context['preserved_build'], + 'allocation_id' => $context['allocation_id'], + 'assigned_allocation_ids' => + $context['assigned_allocation_ids'], + 'source' => $context['source'], + 'target' => $context['target'], + 'delta' => $context['delta'], + ]; + $values = [ + 'purpose' => 'upgrade', + 'idempotency_key' => hash( + 'sha256', + "dynamic-upgrade:{$upgrade->id}:{$fingerprint}" + ), + 'cart_item_id' => null, + 'cart_item_guard_id' => null, + 'cart_id' => null, + 'server_extension_id' => $upgrade->product->server_id, + 'panel_identity' => $context['panel_identity'], + 'service_id' => $upgrade->service_id, + 'service_upgrade_id' => $upgrade->id, + 'upgrade_guard_id' => $upgrade->id, + 'invoice_id' => $upgrade->invoice_id, + 'user_id' => $upgrade->service->user_id, + 'product_id' => $upgrade->product_id, + 'plan_id' => $upgrade->plan_id, + 'quantity' => 1, + 'currency_code' => strtoupper((string) $upgrade->currency_code), + 'configuration_fingerprint' => $fingerprint, + 'configuration_payload' => $payload, + 'pricing_version' => hash('sha256', json_encode([ + 'quoted_amount' => (string) $upgrade->quoted_amount, + 'currency_code' => strtoupper((string) $upgrade->currency_code), + ], JSON_THROW_ON_ERROR)), + 'formula_version' => 'dynamic-upgrade-v1', + // Full target values are provisioning truth. + 'memory' => $context['target']['memory'], + 'cpu' => $context['target']['cpu'], + 'disk' => $context['target']['disk'], + // Capacity accounting uses only positive deltas. + 'reserved_memory' => $context['delta']['memory'], + 'reserved_cpu' => $context['delta']['cpu'], + 'reserved_disk' => $context['delta']['disk'], + 'calculated_price' => (float) $upgrade->quoted_amount, + 'external_server_id' => $context['external_server_id'], + 'external_user_id' => $context['external_user_id'], + 'external_server_uuid' => $context['external_server_uuid'], + 'external_server_identifier' => + $context['external_server_identifier'], + 'pricing_breakdown' => [ + 'kind' => 'resource_upgrade', + 'source' => $context['source'], + 'target' => $context['target'], + 'delta' => $context['delta'], + ], + 'status' => 'pending', + 'expires_at' => $guaranteedUntil, + 'guaranteed_until' => $guaranteedUntil, + 'admin_notes' => 'Capacity held for an immutable service upgrade.', + ]; + + if ($existing !== null) { + $existing->fill($values); + $existing->save(); + + return $existing->fresh(); + } + + return UpgradeReservation::create(array_merge($values, [ + 'token' => Str::random(64), + ])); + }, 5); + } + + /** + * Fulfillment-owned invoice processing calls this for every upgrade while + * this extension is installed, so non-dynamic upgrades deliberately + * delegate to the core lifecycle. + */ + public function commitPaidUpgrade( + ServiceUpgrade $upgrade, + ?Invoice $invoice + ): bool { + $upgrade->loadMissing(['service.product.configOptions', 'product.configOptions']); + if (! $this->usesDynamicCapacity($upgrade)) { + app(ServiceUpgradeService::class)->markPaidCommitted($upgrade); + + return true; + } + + DB::transaction(function () use ($upgrade, $invoice): void { + $lockedInvoice = $invoice !== null + ? Invoice::query() + ->whereKey($invoice->id) + ->lockForUpdate() + ->firstOrFail() + : null; + // Serialize the final billing-anchor proof with renewal, + // cancellation, and any other service mutation. The earlier + // preflight is advisory unless the service is locked again inside + // the transaction that commits the paid upgrade. + Service::query() + ->whereKey($upgrade->service_id) + ->lockForUpdate() + ->firstOrFail(); + $lockedUpgrade = ServiceUpgrade::query() + ->with(['service.product.configOptions', 'product.configOptions']) + ->lockForUpdate() + ->findOrFail($upgrade->id); + $reservation = UpgradeReservation::query() + ->where('purpose', 'upgrade') + ->where('service_upgrade_id', $lockedUpgrade->id) + ->lockForUpdate() + ->firstOrFail(); + + if ($reservation->status === 'paid_committed') { + app(ServiceUpgradeService::class)->markPaidCommitted($lockedUpgrade); + + return; + } + if ($reservation->status !== 'pending') { + throw new DisplayException( + 'The upgrade capacity commitment is no longer payable.' + ); + } + if ($reservation->guaranteed_until?->isPast()) { + throw new DisplayException( + 'The upgrade capacity guarantee has expired.' + ); + } + if ( + ($integrityFailure = $this->reservationIntegrityError( + $lockedUpgrade, + $reservation + )) !== null + ) { + throw new PermanentProvisioningException($integrityFailure); + } + if ( + $lockedInvoice !== null + && $lockedUpgrade->invoice_id !== null + && (int) $lockedUpgrade->invoice_id + !== (int) $lockedInvoice->id + ) { + throw new \RuntimeException( + 'The paid invoice does not belong to this service upgrade.' + ); + } + if ( + $lockedInvoice === null + && ((float) $lockedUpgrade->quoted_amount > 0 + || $lockedUpgrade->invoice_id !== null) + ) { + throw new \RuntimeException( + 'Only an unbilled zero-value or downgrade can be committed without an invoice.' + ); + } + $this->assertServiceAcceptsUpgrade($lockedUpgrade->service); + if ($lockedInvoice !== null) { + $invoiceMismatch = $this->invoiceMismatch( + $lockedUpgrade, + $lockedInvoice + ); + if ($invoiceMismatch !== null) { + throw new \RuntimeException($invoiceMismatch); + } + } + + $reservation->forceFill([ + 'status' => 'paid_committed', + 'invoice_id' => $lockedInvoice?->id, + 'paid_committed_at' => now(), + 'last_provisioning_error' => null, + ])->save(); + + app(ServiceUpgradeService::class)->markPaidCommitted($lockedUpgrade); + }, 5); + + return true; + } + + /** + * Run before the invoice coordinator opens its paid transaction. Invalid + * commitments are persisted first, then surfaced to the caller so a + * gateway cannot turn an expired or drifted upgrade into a paid invoice. + */ + public function preflightPaidUpgrade( + ServiceUpgrade $upgrade, + Invoice $invoice + ): ?string { + return DB::transaction(function () use ($upgrade, $invoice): ?string { + $lockedInvoice = Invoice::query() + ->whereKey($invoice->id) + ->lockForUpdate() + ->firstOrFail(); + Service::query() + ->whereKey($upgrade->service_id) + ->lockForUpdate() + ->firstOrFail(); + $lockedUpgrade = ServiceUpgrade::query() + ->with([ + 'service.product.settings', + 'service.configs.configOption', + 'service.configs.configValue', + 'product.configOptions', + ]) + ->lockForUpdate() + ->findOrFail($upgrade->id); + + if (! $this->usesDynamicCapacity($lockedUpgrade)) { + return null; + } + + $reservation = UpgradeReservation::query() + ->where('purpose', 'upgrade') + ->where('service_upgrade_id', $lockedUpgrade->id) + ->lockForUpdate() + ->first(); + $reason = null; + + if ( + $lockedInvoice->status !== Invoice::STATUS_PENDING + || (int) $lockedUpgrade->invoice_id !== (int) $lockedInvoice->id + ) { + $reason = 'The upgrade invoice is no longer payable.'; + } elseif ( + $lockedUpgrade->service->status !== Service::STATUS_ACTIVE + || $lockedUpgrade->service->cancellation()->exists() + ) { + $reason = 'The service is no longer eligible for this resource upgrade.'; + } elseif ( + ($invoiceMismatch = $this->invoiceMismatch( + $lockedUpgrade, + $lockedInvoice + )) !== null + ) { + $reason = $invoiceMismatch; + } elseif ( + $reservation === null + || $reservation->status !== 'pending' + || $reservation->guaranteed_until?->isPast() + ) { + $reason = 'The upgrade capacity guarantee has expired.'; + } elseif (! $lockedUpgrade->sourceStillMatches()) { + $reason = 'The service changed after the upgrade was quoted.'; + } elseif ( + ($integrityFailure = $this->reservationIntegrityError( + $lockedUpgrade, + $reservation + )) !== null + ) { + $reason = $integrityFailure; + } + + if ($reason === null) { + return null; + } + + $paymentAttention = app( + CapacityInvoicePaymentService::class + )->hasInFlightOrSucceededPayment($lockedInvoice); + $lockedUpgrade->forceFill([ + 'status' => $paymentAttention + ? ServiceUpgrade::STATUS_NEEDS_ATTENTION + : ServiceUpgrade::STATUS_CANCELLED, + 'active_service_guard_id' => $paymentAttention + ? $lockedUpgrade->service_id + : null, + 'last_error' => $paymentAttention + ? "{$reason} External payment evidence exists; refund or account-credit review is required." + : $reason, + 'failed_at' => now(), + ])->save(); + if ($reservation !== null && $reservation->status === 'pending') { + $reservation->forceFill([ + 'status' => $reservation->guaranteed_until?->isPast() + ? 'expired' + : 'cancelled', + 'upgrade_guard_id' => null, + 'admin_notes' => $reason, + ])->save(); + } + if ( + ! $paymentAttention + && $lockedInvoice->status === Invoice::STATUS_PENDING + ) { + app(CancelInvoiceService::class) + ->markCancelledAfterFulfillment($lockedInvoice); + } + + return $reason; + }, 5); + } + + public function expireUnpaidUpgrades(int $limit = 100): int + { + $candidateIds = UpgradeReservation::query() + ->where('purpose', 'upgrade') + ->where('status', 'pending') + ->where('guaranteed_until', '<=', now()) + ->orderBy('id') + ->limit($limit) + ->pluck('id'); + $expired = 0; + + foreach ($candidateIds as $reservationId) { + $didExpire = DB::transaction(function () use ($reservationId): bool { + $candidate = UpgradeReservation::query()->find($reservationId); + if ($candidate === null) { + return false; + } + + $invoice = $candidate->invoice_id !== null + ? Invoice::query() + ->whereKey($candidate->invoice_id) + ->lockForUpdate() + ->first() + : null; + $serviceId = ServiceUpgrade::query() + ->whereKey($candidate->service_upgrade_id) + ->value('service_id'); + if ($serviceId !== null) { + Service::query() + ->whereKey($serviceId) + ->lockForUpdate() + ->firstOrFail(); + } + $upgrade = ServiceUpgrade::query() + ->whereKey($candidate->service_upgrade_id) + ->lockForUpdate() + ->first(); + $reservation = UpgradeReservation::query() + ->whereKey($reservationId) + ->lockForUpdate() + ->first(); + if ($invoice !== null) { + $invoice->items() + ->orderBy('id') + ->lockForUpdate() + ->get(); + } + + if ( + $reservation === null + || $reservation->status !== 'pending' + || $reservation->guaranteed_until?->isFuture() + || $invoice?->status === Invoice::STATUS_PAID + ) { + return false; + } + + $reason = 'The unpaid upgrade capacity guarantee expired.'; + $paymentAttention = $invoice !== null + && $invoice->status === Invoice::STATUS_PENDING + && app(CapacityInvoicePaymentService::class) + ->hasInFlightOrSucceededPayment($invoice); + $reservation->forceFill([ + 'status' => 'expired', + 'upgrade_guard_id' => null, + 'admin_notes' => $reason, + ])->save(); + if ($upgrade !== null && in_array($upgrade->status, [ + ServiceUpgrade::STATUS_PENDING, + ServiceUpgrade::STATUS_AWAITING_PAYMENT, + ], true)) { + $upgrade->forceFill([ + 'status' => $paymentAttention + ? ServiceUpgrade::STATUS_NEEDS_ATTENTION + : ServiceUpgrade::STATUS_CANCELLED, + 'active_service_guard_id' => $paymentAttention + ? $upgrade->service_id + : null, + 'last_error' => $paymentAttention + ? 'The capacity guarantee expired with payment activity; refund or account-credit review is required.' + : $reason, + 'failed_at' => now(), + ])->save(); + } + if ($paymentAttention) { + app(CapacityInvoicePaymentService::class)->requireAttention( + $invoice, + 'The seven-day upgrade capacity guarantee expired after a partial or in-flight payment. Capacity was released; refund or account-credit review is required.' + ); + } elseif ($invoice?->status === Invoice::STATUS_PENDING) { + app(CancelInvoiceService::class) + ->markCancelledAfterFulfillment($invoice); + } + + return true; + }, 5); + + $expired += $didExpire ? 1 : 0; + } + + return $expired; + } + + public function reconcileStalledUpgrades(int $limit = 100): int + { + $upgradeIds = ServiceUpgrade::query() + ->where('status', ServiceUpgrade::STATUS_PROVISIONING) + ->where('provisioning_started_at', '<=', now()->subMinutes(10)) + ->orderBy('id') + ->limit($limit) + ->pluck('id'); + $requeued = 0; + + foreach ($upgradeIds as $upgradeId) { + $didRequeue = DB::transaction(function () use ($upgradeId): bool { + $upgrade = ServiceUpgrade::query() + ->whereKey($upgradeId) + ->lockForUpdate() + ->first(); + $reservation = UpgradeReservation::query() + ->where('purpose', 'upgrade') + ->where('service_upgrade_id', $upgradeId) + ->lockForUpdate() + ->first(); + + if ( + $upgrade === null + || $reservation === null + || $upgrade->status !== ServiceUpgrade::STATUS_PROVISIONING + || $upgrade->provisioning_started_at?->isAfter(now()->subMinutes(10)) + || $reservation->status !== 'paid_committed' + ) { + return false; + } + + $message = 'A stale upgrade worker lease was recovered for retry.'; + $reservation->forceFill([ + 'provisioning_lease_id' => null, + 'provisioning_started_at' => null, + 'last_provisioning_error' => $message, + ])->save(); + $upgrade->forceFill([ + 'status' => ServiceUpgrade::STATUS_RETRYABLE_FAILED, + 'last_error' => $message, + 'failed_at' => now(), + ])->save(); + + DB::afterCommit( + fn () => UpgradeJob::dispatch( + ServiceUpgrade::query()->findOrFail($upgradeId) + ) + ); + + return true; + }, 5); + + $requeued += $didRequeue ? 1 : 0; + } + + return $requeued; + } + + /** + * Acquire a retry-safe provisioning lease and return the exact contract + * passed to the built-in Pterodactyl extension. + * + * @return array + */ + public function beginProvisioning(ServiceUpgrade $upgrade): array + { + return DB::transaction(function () use ($upgrade): array { + $service = Service::query() + ->whereKey($upgrade->service_id) + ->lockForUpdate() + ->firstOrFail(); + $lockedUpgrade = ServiceUpgrade::query() + ->whereKey($upgrade->id) + ->lockForUpdate() + ->firstOrFail(); + if ((int) $lockedUpgrade->service_id !== (int) $service->id) { + throw new PermanentProvisioningException( + 'The paid upgrade no longer belongs to its locked service.' + ); + } + if (! $this->serviceAcceptsUpgrade($service)) { + throw new PermanentProvisioningException( + 'The service was cancelled before its paid upgrade could be applied.' + ); + } + $reservation = UpgradeReservation::query() + ->where('purpose', 'upgrade') + ->where('service_upgrade_id', $lockedUpgrade->id) + ->lockForUpdate() + ->firstOrFail(); + + if ($reservation->status !== 'paid_committed') { + throw new PermanentProvisioningException( + 'The upgrade does not have a paid capacity commitment.' + ); + } + + if ( + $reservation->provisioning_lease_id !== null + && $reservation->provisioning_started_at?->gt(now()->subMinutes(10)) + ) { + throw new \RuntimeException( + 'Another worker currently owns this upgrade provisioning lease.' + ); + } + + $payload = (array) $reservation->configuration_payload; + if ( + ($integrityFailure = $this->reservationIntegrityError( + $lockedUpgrade, + $reservation + )) !== null + ) { + throw new PermanentProvisioningException( + $integrityFailure + ); + } + + $leaseId = (string) Str::uuid(); + $reservation->forceFill([ + 'provisioning_lease_id' => $leaseId, + 'provisioning_started_at' => now(), + 'provisioning_attempts' => (int) $reservation->provisioning_attempts + 1, + 'last_provisioning_attempt_at' => now(), + 'last_provisioning_error' => null, + ])->save(); + + return [ + 'reservation_id' => (int) $reservation->id, + 'provisioning_lease_id' => $leaseId, + 'panel_identity' => (string) $reservation->panel_identity, + 'node_id' => (int) $reservation->node_id, + 'location_id' => (int) $reservation->location_id, + 'source' => (array) ($payload['source'] ?? []), + 'target' => (array) ($payload['target'] ?? []), + 'external_server_id' => (int) ($payload['external_server_id'] ?? 0), + 'external_server_uuid' => + (string) ($payload['external_server_uuid'] ?? ''), + 'external_server_identifier' => + (string) ($payload['external_server_identifier'] ?? ''), + 'external_server_external_id' => + (string) ($payload['external_server_external_id'] ?? ''), + 'external_user_id' => + (int) ($payload['external_user_id'] ?? 0), + 'user_external_id' => + (string) ($payload['user_external_id'] ?? ''), + 'user_email' => (string) ($payload['user_email'] ?? ''), + 'nest_id' => (int) ($payload['nest_id'] ?? 0), + 'egg_id' => (int) ($payload['egg_id'] ?? 0), + 'preserved_build' => (array) ( + $payload['preserved_build'] ?? [] + ), + 'allocation_id' => (int) ($payload['allocation_id'] ?? 0), + 'assigned_allocation_ids' => array_values(array_map( + 'intval', + (array) ($payload['assigned_allocation_ids'] ?? []) + )), + ]; + }, 5); + } + + public function completeProvisioning( + ServiceUpgrade $upgrade, + ?string $leaseId + ): void { + if ($leaseId === null || $leaseId === '') { + throw new \RuntimeException('An upgrade provisioning lease is required.'); + } + + $reservation = UpgradeReservation::query() + ->where('purpose', 'upgrade') + ->where('service_upgrade_id', $upgrade->id) + ->lockForUpdate() + ->firstOrFail(); + + if ($reservation->status === 'confirmed') { + return; + } + if ( + $reservation->status !== 'paid_committed' + || ! hash_equals((string) $reservation->provisioning_lease_id, $leaseId) + ) { + throw new \RuntimeException( + 'The upgrade provisioning lease is stale or invalid.' + ); + } + + $reservation->forceFill([ + 'status' => 'confirmed', + 'upgrade_guard_id' => null, + 'provisioning_lease_id' => null, + 'consumed_at' => now(), + 'last_provisioning_error' => null, + ])->save(); + } + + public function failProvisioning( + ServiceUpgrade $upgrade, + \Throwable $exception, + ?string $leaseId = null + ): bool { + $reservation = UpgradeReservation::query() + ->where('purpose', 'upgrade') + ->where('service_upgrade_id', $upgrade->id) + ->lockForUpdate() + ->first(); + if ($reservation === null || $reservation->status !== 'paid_committed') { + return false; + } + if ($leaseId === null) { + if ($reservation->provisioning_lease_id !== null) { + return false; + } + } elseif ( + $reservation->provisioning_lease_id === null + || ! hash_equals( + (string) $reservation->provisioning_lease_id, + $leaseId + ) + ) { + return false; + } + + $reservation->forceFill([ + 'provisioning_lease_id' => null, + 'provisioning_started_at' => null, + 'last_provisioning_error' => mb_substr($exception->getMessage(), 0, 65535), + ])->save(); + + return true; + } + + public function cancelUpgrade(ServiceUpgrade $upgrade, string $reason): void + { + $reservation = UpgradeReservation::query() + ->where('purpose', 'upgrade') + ->where('service_upgrade_id', $upgrade->id) + ->lockForUpdate() + ->first(); + if ($reservation === null || $reservation->status === 'cancelled') { + return; + } + if ($reservation->status !== 'pending') { + throw new \RuntimeException( + 'Only an unpaid upgrade capacity hold can be cancelled.' + ); + } + + $reservation->forceFill([ + 'status' => 'cancelled', + 'upgrade_guard_id' => null, + 'admin_notes' => $reason, + ])->save(); + } + + /** + * Authenticated, customer-safe bounds for an existing server's fixed node. + * + * @param array $submittedOptions + * @return array + */ + public function quoteForService(Service $service, array $submittedOptions): array + { + if (DB::transactionLevel() === 0) { + return DB::transaction( + fn (): array => $this->quoteForService( + $service, + $submittedOptions + ), + 5 + ); + } + + $lockedProduct = app( + \App\Services\Service\CapacityConfigurationLockService::class + )->lockProduct((int) $service->product_id); + $service->setRelation('product', $lockedProduct); + $this->inventory->assertExclusiveProvisioningControl(); + $service->loadMissing([ + 'product.upgradableConfigOptions', + 'product.server.settings', + 'configs.configOption', + ]); + $this->assertServiceAcceptsUpgrade($service); + + if (! $service->product->usesDynamicResources()) { + throw new InvalidStockConfigurationException( + 'This service does not use dynamic resources.' + ); + } + + $this->assertProductPanel($service); + $server = $this->inventory->serverByExternalId($service->id); + $checkoutIdentity = $this->checkoutServerIdentity($service); + $this->assertExternalServerMatchesCheckout( + $server, + $checkoutIdentity, + (int) $service->id + ); + $node = collect($this->inventory->nodes())->firstWhere('id', $server['node']); + if (! is_array($node)) { + throw new InvalidStockConfigurationException( + 'The service node is missing from Pterodactyl inventory.' + ); + } + + $allOptions = $service->product->upgradableConfigOptions->keyBy('id'); + $options = $allOptions + ->filter(fn ($option): bool => $option->isDynamicSlider()); + $submitted = collect($submittedOptions) + ->mapWithKeys(fn ($value, $key): array => [(int) $key => $value]); + $unknown = $submitted->keys()->diff($allOptions->keys()); + if ($unknown->isNotEmpty()) { + throw new InvalidResourceSelectionException( + 'The resource upgrade contains an unknown option.' + ); + } + + $selection = [ + 'memory' => $server['memory'], + 'cpu' => $server['cpu'], + 'disk' => $server['disk'], + ]; + $sliders = []; + foreach ($options as $option) { + $resource = strtolower((string) $option->getMetadata('resource_type', '')); + if (! in_array($resource, ['memory', 'cpu', 'disk'], true)) { + continue; + } + if (array_key_exists($resource, $sliders)) { + throw new InvalidStockConfigurationException( + "Multiple active {$resource} sliders are attached to this product." + ); + } + + $minimum = $this->metadataInteger($option, 'min'); + $maximum = $this->metadataInteger($option, 'max'); + $step = $this->metadataInteger($option, 'step'); + $value = $submitted->has($option->id) + ? $option->normalizeDynamicSliderValue($submitted->get($option->id)) + : $selection[$resource]; + $selection[$resource] = $value; + $sliders[$resource] = [ + 'config_option_id' => (int) $option->id, + 'min' => $minimum, + 'max' => $maximum, + 'step' => $step, + ]; + } + + if ($sliders === []) { + throw new InvalidStockConfigurationException( + 'No dynamic resource is enabled for upgrades.' + ); + } + + $availability = $this->resources->getNodeAvailability($server['node']); + if ($availability === null) { + throw new StockUnavailableException( + 'The current server node is not available.' + ); + } + + $bounds = []; + $adjusted = false; + foreach ($sliders as $resource => $slider) { + $minimum = $resource === 'disk' + ? $this->snapUp( + max($slider['min'], $server['disk']), + $slider['min'], + $slider['step'] + ) + : $slider['min']; + $maximum = $this->snapDown( + min( + $slider['max'], + $server[$resource] + (int) $availability['available'][$resource] + ), + $slider['min'], + $slider['step'] + ); + + if ($maximum < $minimum) { + throw new StockUnavailableException( + "The current node cannot satisfy the {$resource} upgrade minimum." + ); + } + + $candidate = min($maximum, max($minimum, $selection[$resource])); + $candidate = $this->snapDown( + $candidate, + $slider['min'], + $slider['step'] + ); + if ($candidate !== $selection[$resource]) { + $selection[$resource] = $candidate; + $adjusted = true; + } + + $bounds[$resource] = [ + 'config_option_id' => $slider['config_option_id'], + 'min' => $minimum, + 'max' => $maximum, + 'configured_max' => $slider['max'], + 'step' => $slider['step'], + ]; + } + + $delta = $this->positiveDelta($server, $selection); + if (! $this->resources->verifyNodeCapacity($server['node'], $delta, 0)) { + throw new StockUnavailableException( + 'The current node cannot satisfy the complete resource upgrade.' + ); + } + + return [ + 'available' => true, + 'adjusted' => $adjusted, + 'selection' => $selection, + 'bounds' => $bounds, + ]; + } + + /** + * @return array + */ + private function upgradeContext( + ServiceUpgrade $upgrade, + bool $requireSourceMatch + ): array { + $upgrade->loadMissing([ + 'service.product.server.settings', + 'service.product.configOptions', + 'service.user', + 'product.server.settings', + 'product.configOptions', + ]); + $this->assertServiceAcceptsUpgrade($upgrade->service); + if (! $this->usesDynamicCapacity($upgrade)) { + throw new InvalidStockConfigurationException( + 'This upgrade does not use dynamic capacity.' + ); + } + if ((int) $upgrade->product_id !== (int) $upgrade->service->product_id) { + throw new InvalidResourceSelectionException( + 'Dynamic resource upgrades cannot change products.' + ); + } + if ((int) $upgrade->plan_id !== (int) $upgrade->service->plan_id) { + throw new InvalidResourceSelectionException( + 'Dynamic resource upgrades cannot change billing plans.' + ); + } + $this->assertOnlyResourcePropertiesChanged($upgrade); + + $this->assertProductPanel($upgrade->service); + $server = $this->inventory->serverByExternalId($upgrade->service_id); + $checkoutIdentity = $this->checkoutServerIdentity( + $upgrade->service + ); + $node = collect($this->inventory->nodes())->firstWhere('id', $server['node']); + if (! is_array($node)) { + throw new InvalidStockConfigurationException( + 'The existing Pterodactyl node is unavailable.' + ); + } + + $this->assertExternalServerMatchesCheckout( + $server, + $checkoutIdentity, + (int) $upgrade->service_id + ); + $sourceProperties = (array) data_get( + $upgrade->source_snapshot, + 'properties', + [] + ); + $source = $this->resourceVector($sourceProperties, 'source'); + $targetResources = $upgrade->targetResources(); + $targetLocation = $targetResources['location']; + $target = $targetResources; + unset($target['location']); + if ($source === $target) { + throw new InvalidResourceSelectionException( + 'A dynamic upgrade must change at least one of RAM, CPU, or disk.' + ); + } + + if ($requireSourceMatch) { + foreach (['memory', 'cpu', 'disk'] as $resource) { + if ((int) $server[$resource] !== $source[$resource]) { + throw new InvalidResourceSelectionException( + "Pterodactyl {$resource} no longer matches the service being upgraded." + ); + } + } + } + + if ( + $targetLocation <= 0 + || $targetLocation !== (int) $node['location_id'] + ) { + throw new InvalidResourceSelectionException( + 'Dynamic upgrades must remain in the existing Pterodactyl location.' + ); + } + if ($target['disk'] < $server['disk']) { + throw new InvalidResourceSelectionException( + 'Pterodactyl disk cannot be reduced by this upgrade workflow.' + ); + } + + return [ + 'panel_identity' => $checkoutIdentity['panel_identity'], + 'node_id' => (int) $server['node'], + 'location_id' => (int) $node['location_id'], + 'external_server_id' => $checkoutIdentity['id'], + 'external_server_uuid' => $checkoutIdentity['uuid'], + 'external_server_identifier' => + $checkoutIdentity['identifier'], + 'external_server_external_id' => + (string) $upgrade->service_id, + 'external_user_id' => $checkoutIdentity['external_user_id'], + 'user_external_id' => $checkoutIdentity['user_external_id'], + 'user_email' => $checkoutIdentity['user_email'], + 'nest_id' => $checkoutIdentity['nest_id'], + 'egg_id' => $checkoutIdentity['egg_id'], + 'preserved_build' => $this->preservedBuild($server), + 'allocation_id' => (int) $server['allocation'], + 'assigned_allocation_ids' => $this->assignedAllocationIds($server), + 'source' => $source, + 'target' => $target, + 'delta' => $this->positiveDelta($server, $target), + ]; + } + + /** + * The original checkout commitment is the durable proof that this exact + * external server—not merely any server reusing the same external ID—is + * eligible for an in-place resource upgrade. + * + * @return array{ + * id: int, + * uuid: string, + * identifier: string, + * panel_identity: string, + * external_user_id: int, + * nest_id: int, + * egg_id: int, + * user_external_id: string, + * user_email: string + * } + */ + private function checkoutServerIdentity(Service $service): array + { + $reservation = DB::table('ptero_resource_reservations') + ->where('purpose', 'checkout') + ->where('service_id', $service->id) + ->where('status', 'confirmed') + ->orderByDesc('id') + ->first(); + $id = StrictInteger::parse($reservation?->external_server_id); + $externalUserId = StrictInteger::parse( + $reservation?->external_user_id + ); + $uuid = $reservation?->external_server_uuid; + $identifier = $reservation?->external_server_identifier; + try { + $payload = json_decode( + (string) ($reservation?->configuration_payload ?? ''), + true, + 512, + JSON_THROW_ON_ERROR + ); + } catch (\JsonException $exception) { + throw new InvalidStockConfigurationException( + 'The confirmed checkout commitment is unreadable.', + previous: $exception + ); + } + $configuration = new ReservationConfigurationService; + $identity = is_array($payload) + ? (array) ($payload['provisioning_identity'] ?? []) + : []; + $panelIdentity = is_array($payload) + ? (string) ($payload['panel_identity'] ?? '') + : ''; + $nestId = StrictInteger::parse($identity['nest_id'] ?? null); + $eggId = StrictInteger::parse($identity['egg_id'] ?? null); + $userExternalId = trim((string) ( + $identity['user_external_id'] ?? '' + )); + $userEmail = strtolower(trim((string) ( + $identity['user_email'] ?? '' + ))); + $expectedUserExternalId = "paymenter-user-{$service->user_id}"; + if ( + $reservation === null + || $id === null + || $id <= 0 + || $externalUserId === null + || $externalUserId <= 0 + || ! is_string($uuid) + || ! Str::isUuid($uuid) + || ! is_string($identifier) + || trim($identifier) === '' + || ! is_array($payload) + || ! hash_equals( + (string) $reservation->configuration_fingerprint, + $configuration->fingerprint($payload) + ) + || (int) $reservation->user_id !== (int) $service->user_id + || (int) $reservation->product_id !== (int) $service->product_id + || (int) $reservation->plan_id !== (int) $service->plan_id + || (int) ($payload['customer_id'] ?? 0) + !== (int) $reservation->user_id + || (int) ($payload['product_id'] ?? 0) + !== (int) $reservation->product_id + || (int) ($payload['plan_id'] ?? 0) + !== (int) $reservation->plan_id + || ! is_string($reservation->panel_identity) + || preg_match('/^[a-f0-9]{64}$/D', $panelIdentity) !== 1 + || ! hash_equals( + (string) $reservation->panel_identity, + $panelIdentity + ) + || ! hash_equals( + $this->inventory->panelIdentity(), + $panelIdentity + ) + || $nestId === null + || $nestId <= 0 + || $eggId === null + || $eggId <= 0 + || $userEmail === '' + || ! hash_equals($expectedUserExternalId, $userExternalId) + ) { + throw new InvalidStockConfigurationException( + 'Dynamic upgrades require the exact external server identity from a confirmed checkout commitment.' + ); + } + + return [ + 'id' => $id, + 'uuid' => $uuid, + 'identifier' => trim($identifier), + 'panel_identity' => $panelIdentity, + 'external_user_id' => $externalUserId, + 'nest_id' => $nestId, + 'egg_id' => $eggId, + 'user_external_id' => $userExternalId, + 'user_email' => $userEmail, + ]; + } + + /** + * @param array $server + * @param array $checkoutIdentity + */ + private function assertExternalServerMatchesCheckout( + array $server, + array $checkoutIdentity, + int $serviceId + ): void { + if ( + (int) ($server['id'] ?? 0) !== $checkoutIdentity['id'] + || ! hash_equals( + $checkoutIdentity['uuid'], + (string) ($server['uuid'] ?? '') + ) + || ! hash_equals( + $checkoutIdentity['identifier'], + (string) ($server['identifier'] ?? '') + ) + || ! hash_equals( + (string) $serviceId, + (string) ($server['external_id'] ?? '') + ) + || StrictInteger::parse($server['user_id'] ?? null) === null + || (int) $server['user_id'] + !== $checkoutIdentity['external_user_id'] + || ! hash_equals( + $checkoutIdentity['user_external_id'], + (string) ($server['user_external_id'] ?? '') + ) + || (int) ($server['nest_id'] ?? 0) + !== $checkoutIdentity['nest_id'] + || (int) ($server['egg_id'] ?? 0) + !== $checkoutIdentity['egg_id'] + ) { + throw new InvalidResourceSelectionException( + 'The Pterodactyl server identity no longer matches the immutable checkout commitment.' + ); + } + } + + private function assertProductPanel(Service $service): void + { + $server = $service->product->server; + if ($server === null || $server->extension !== 'Pterodactyl') { + throw new InvalidStockConfigurationException( + 'Dynamic resources require the Pterodactyl server extension.' + ); + } + + $settings = ExtensionHelper::settingsToArray($server->settings); + $host = trim((string) ($settings['host'] ?? '')); + try { + $panelIdentity = PanelEndpointIdentity::hash($host); + } catch (\InvalidArgumentException) { + $panelIdentity = ''; + } + if ( + $panelIdentity === '' + || ! hash_equals( + $this->inventory->panelIdentity(), + $panelIdentity + ) + ) { + throw new InvalidStockConfigurationException( + 'The stock service and provisioner target different Pterodactyl panels.' + ); + } + } + + private function assertOnlyResourcePropertiesChanged( + ServiceUpgrade $upgrade + ): void { + $source = collect((array) data_get( + $upgrade->source_snapshot, + 'properties', + [] + ))->mapWithKeys(fn ($value, $key): array => [ + strtolower((string) $key) => $value, + ])->all(); + $target = collect((array) data_get( + $upgrade->target_snapshot, + 'properties', + [] + ))->mapWithKeys(fn ($value, $key): array => [ + strtolower((string) $key) => $value, + ])->all(); + $keys = array_unique(array_merge( + array_keys($source), + array_keys($target) + )); + + foreach ($keys as $key) { + if (in_array($key, ['memory', 'cpu', 'disk'], true)) { + continue; + } + if ( + ! array_key_exists($key, $source) + || ! array_key_exists($key, $target) + || $source[$key] !== $target[$key] + ) { + throw new InvalidResourceSelectionException( + 'Dynamic upgrades may change only RAM, CPU, and disk.' + ); + } + } + } + + private function lockCapacityScope(string $panelIdentity, int $locationId): void + { + DB::table('ptero_capacity_scopes')->insertOrIgnore([ + 'panel_identity' => $panelIdentity, + 'location_id' => $locationId, + 'created_at' => now(), + 'updated_at' => now(), + ]); + DB::table('ptero_capacity_scopes') + ->where('panel_identity', $panelIdentity) + ->where('location_id', $locationId) + ->lockForUpdate() + ->first(); + } + + /** + * @param array $properties + * @return array{memory: int, cpu: int, disk: int} + */ + private function resourceVector(array $properties, string $label): array + { + $properties = collect($properties) + ->mapWithKeys(fn ($value, $key): array => [ + strtolower((string) $key) => $value, + ]); + $vector = []; + foreach (['memory', 'cpu', 'disk'] as $resource) { + $vector[$resource] = $this->wholeNumber( + $properties->get($resource), + "{$label} {$resource}" + ); + } + + return $vector; + } + + /** + * @param array $source + * @param array $target + * @return array{memory: int, cpu: int, disk: int} + */ + private function positiveDelta(array $source, array $target): array + { + return [ + 'memory' => max(0, (int) $target['memory'] - (int) $source['memory']), + 'cpu' => max(0, (int) $target['cpu'] - (int) $source['cpu']), + 'disk' => max(0, (int) $target['disk'] - (int) $source['disk']), + ]; + } + + private function wholeNumber(mixed $value, string $label): int + { + $numeric = StrictInteger::parse($value) + ?? StrictInteger::parseStoredDecimal($value); + if ($numeric === null || $numeric < 0) { + throw new InvalidStockConfigurationException( + "The {$label} value must be a non-negative whole number." + ); + } + + return $numeric; + } + + private function metadataInteger(object $option, string $key): int + { + $value = $this->wholeNumber( + $option->getMetadata($key), + "{$option->name} {$key}" + ); + if ($key === 'step' && $value <= 0) { + throw new InvalidStockConfigurationException( + "{$option->name} step must be positive." + ); + } + + return $value; + } + + private function reservationFingerprint( + ServiceUpgrade $upgrade, + array $context + ): string { + return hash('sha256', json_encode([ + 'upgrade_id' => (int) $upgrade->id, + 'source_fingerprint' => (string) $upgrade->source_fingerprint, + 'target_fingerprint' => (string) $upgrade->target_fingerprint, + 'panel_identity' => $context['panel_identity'], + 'node_id' => $context['node_id'], + 'location_id' => $context['location_id'], + 'external_server_id' => $context['external_server_id'], + 'external_server_uuid' => $context['external_server_uuid'], + 'external_server_identifier' => + $context['external_server_identifier'], + 'external_server_external_id' => + $context['external_server_external_id'], + 'external_user_id' => $context['external_user_id'], + 'user_external_id' => $context['user_external_id'], + 'user_email' => $context['user_email'], + 'nest_id' => $context['nest_id'], + 'egg_id' => $context['egg_id'], + 'preserved_build' => $context['preserved_build'], + 'allocation_id' => $context['allocation_id'], + 'assigned_allocation_ids' => $context['assigned_allocation_ids'], + 'source' => $context['source'], + 'target' => $context['target'], + 'delta' => $context['delta'], + 'quoted_amount' => (string) $upgrade->quoted_amount, + 'currency_code' => strtoupper((string) $upgrade->currency_code), + ], JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES)); + } + + private function reservationIntegrityError( + ServiceUpgrade $upgrade, + UpgradeReservation $reservation + ): ?string { + $payload = $reservation->configuration_payload; + if (! is_array($payload)) { + return 'The paid upgrade reservation failed its immutable integrity check.'; + } + + try { + $fingerprint = $this->reservationFingerprint($upgrade, $payload); + } catch (\Throwable) { + return 'The paid upgrade reservation failed its immutable integrity check.'; + } + $target = $payload['target'] ?? null; + $delta = $payload['delta'] ?? null; + if ( + ! is_array($target) + || ! is_array($delta) + || ! is_string($reservation->configuration_fingerprint) + || ! hash_equals( + $reservation->configuration_fingerprint, + $fingerprint + ) + || (int) $reservation->service_id + !== (int) $upgrade->service_id + || (int) $reservation->service_upgrade_id + !== (int) $upgrade->id + || (int) ($payload['service_upgrade_id'] ?? 0) + !== (int) $upgrade->id + || (string) ($payload['source_fingerprint'] ?? '') + !== (string) $upgrade->source_fingerprint + || (string) ($payload['target_fingerprint'] ?? '') + !== (string) $upgrade->target_fingerprint + || (string) ($payload['panel_identity'] ?? '') + !== (string) $reservation->panel_identity + || (int) ($payload['node_id'] ?? 0) + !== (int) $reservation->node_id + || (int) ($payload['location_id'] ?? 0) + !== (int) $reservation->location_id + || (int) ($payload['external_server_id'] ?? 0) + !== (int) $reservation->external_server_id + || (int) ($payload['external_user_id'] ?? 0) + !== (int) $reservation->external_user_id + || (string) ($payload['external_server_uuid'] ?? '') + !== (string) $reservation->external_server_uuid + || (string) ($payload['external_server_identifier'] ?? '') + !== (string) $reservation->external_server_identifier + || (int) ($target['memory'] ?? -1) + !== (int) $reservation->memory + || (int) ($target['cpu'] ?? -1) + !== (int) $reservation->cpu + || (int) ($target['disk'] ?? -1) + !== (int) $reservation->disk + || (int) ($delta['memory'] ?? -1) + !== (int) $reservation->reserved_memory + || (int) ($delta['cpu'] ?? -1) + !== (int) $reservation->reserved_cpu + || (int) ($delta['disk'] ?? -1) + !== (int) $reservation->reserved_disk + ) { + return 'The paid upgrade reservation failed its immutable integrity check.'; + } + + return null; + } + + private function usesDynamicCapacity(ServiceUpgrade $upgrade): bool + { + return $upgrade->service->product->usesDynamicResources() + || $upgrade->product->usesDynamicResources(); + } + + /** + * Freeze every remote build field that a RAM/CPU/disk-only upgrade must + * preserve across queue retries. + * + * @param array $server + * @return array{ + * swap: int, + * io: int, + * threads: string|null, + * databases: int, + * allocations: int, + * backups: int + * } + */ + private function preservedBuild(array $server): array + { + $threads = $server['threads'] ?? null; + $values = [ + 'swap' => StrictInteger::parse($server['swap'] ?? null), + 'io' => StrictInteger::parse($server['io'] ?? null), + 'databases' => StrictInteger::parse( + $server['database_limit'] ?? null + ), + 'allocations' => StrictInteger::parse( + $server['allocation_limit'] ?? null + ), + 'backups' => StrictInteger::parse( + $server['backup_limit'] ?? null + ), + ]; + if ( + ($threads !== null && ! is_string($threads)) + || $values['swap'] === null + || $values['swap'] < 0 + || $values['io'] === null + || $values['io'] < 0 + || $values['databases'] === null + || $values['databases'] < 0 + || $values['allocations'] !== 0 + || $values['backups'] === null + || $values['backups'] < 0 + ) { + throw new InvalidStockConfigurationException( + 'Resource-only upgrades require complete remote build limits and a zero client allocation limit.' + ); + } + + return [ + 'swap' => $values['swap'], + 'io' => $values['io'], + 'threads' => $threads, + 'databases' => $values['databases'], + 'allocations' => $values['allocations'], + 'backups' => $values['backups'], + ]; + } + + /** + * @param array $server + * @return list + */ + private function assignedAllocationIds(array $server): array + { + $ids = $server['assigned_allocation_ids'] ?? null; + if (! is_array($ids) || ! array_is_list($ids)) { + throw new InvalidStockConfigurationException( + 'Pterodactyl did not return the server allocation set.' + ); + } + + $normalized = []; + foreach ($ids as $id) { + $parsed = StrictInteger::parse($id); + if ($parsed === null || $parsed <= 0) { + throw new InvalidStockConfigurationException( + 'Pterodactyl returned an invalid server allocation set.' + ); + } + $normalized[] = $parsed; + } + sort($normalized, SORT_NUMERIC); + if ( + $normalized === [] + || count(array_unique($normalized)) !== count($normalized) + || ! in_array((int) ($server['allocation'] ?? 0), $normalized, true) + ) { + throw new InvalidStockConfigurationException( + 'Pterodactyl returned an inconsistent server allocation set.' + ); + } + + return $normalized; + } + + private function assertServiceAcceptsUpgrade(Service $service): void + { + if (! $this->serviceAcceptsUpgrade($service)) { + throw new InvalidResourceSelectionException( + 'The service is not active or already has a cancellation request.' + ); + } + } + + private function serviceAcceptsUpgrade(Service $service): bool + { + return $service->status === Service::STATUS_ACTIVE + && ! $service->cancellation()->exists(); + } + + private function invoiceMismatch( + ServiceUpgrade $upgrade, + Invoice $invoice + ): ?string { + $items = $invoice->items() + ->orderBy('id') + ->lockForUpdate() + ->get(); + if ( + (int) $invoice->user_id !== (int) $upgrade->service->user_id + || strtoupper((string) $invoice->currency_code) + !== strtoupper((string) $upgrade->currency_code) + || $items->count() !== 1 + ) { + return 'The upgrade invoice identity no longer matches its immutable quote.'; + } + + $item = $items->first(); + $actualCents = $this->moneyCents($item->price); + $expectedCents = $this->moneyCents($upgrade->quoted_amount); + if ( + $item->reference_type !== ServiceUpgrade::class + || (int) $item->reference_id !== (int) $upgrade->id + || (int) $item->quantity !== 1 + || $expectedCents === null + || $expectedCents <= 0 + || $actualCents !== $expectedCents + ) { + return 'The upgrade invoice line no longer matches its immutable quote.'; + } + + return null; + } + + private function moneyCents(mixed $value): ?int + { + $text = is_int($value) + ? (string) $value + : (is_string($value) ? $value : ''); + if ( + preg_match('/^(-?)(0|[1-9]\d*)(?:\.(\d+))?$/D', $text, $matches) + !== 1 + ) { + return null; + } + + $whole = StrictInteger::parse( + ($matches[1] ?? '').$matches[2] + ); + $fraction = $matches[3] ?? ''; + if ( + $whole === null + || (strlen($fraction) > 2 + && trim(substr($fraction, 2), '0') !== '') + || abs($whole) > intdiv(PHP_INT_MAX - 99, 100) + ) { + return null; + } + + $fraction = str_pad(substr($fraction, 0, 2), 2, '0'); + $cents = abs($whole) * 100 + (int) $fraction; + + return ($matches[1] ?? '') === '-' ? -$cents : $cents; + } + + private function snapDown(int $value, int $minimum, int $step): int + { + return $value < $minimum + ? $minimum - 1 + : $minimum + intdiv($value - $minimum, $step) * $step; + } + + private function snapUp(int $value, int $minimum, int $step): int + { + if ($value <= $minimum) { + return $minimum; + } + + return $minimum + (int) ceil(($value - $minimum) / $step) * $step; + } +} diff --git a/database/migrations/2026_07_26_000001_add_durable_fulfillment_to_ptero_reservations.php b/database/migrations/2026_07_26_000001_add_durable_fulfillment_to_ptero_reservations.php new file mode 100644 index 0000000..5f2a04f --- /dev/null +++ b/database/migrations/2026_07_26_000001_add_durable_fulfillment_to_ptero_reservations.php @@ -0,0 +1,195 @@ + $table + ->enum('status', $statuses) + ->default('pending') + ->change() + ); + } + + Schema::table('ptero_resource_reservations', function (Blueprint $table) { + $table->unsignedBigInteger('invoice_id')->nullable()->after('service_id'); + $table->timestamp('guaranteed_until')->nullable()->after('expires_at'); + $table->timestamp('paid_committed_at')->nullable()->after('guaranteed_until'); + $table->unsignedInteger('provisioning_attempts')->default(0)->after('provisioning_started_at'); + $table->timestamp('last_provisioning_attempt_at')->nullable()->after('provisioning_attempts'); + $table->timestamp('next_provisioning_attempt_at')->nullable()->after('last_provisioning_attempt_at'); + $table->timestamp('failure_alerted_at')->nullable()->after('last_provisioning_error'); + $table->timestamp('cancellation_requested_at')->nullable()->after('failure_alerted_at'); + $table->text('last_cancellation_error')->nullable()->after('cancellation_requested_at'); + $table->timestamp('cancellation_failure_alerted_at')->nullable()->after('last_cancellation_error'); + $table->unsignedBigInteger('external_server_id')->nullable()->after('cancellation_failure_alerted_at'); + $table->unsignedBigInteger('external_user_id')->nullable()->after('external_server_id'); + $table->uuid('external_server_uuid')->nullable()->after('external_user_id'); + $table->string('external_server_identifier', 64)->nullable()->after('external_server_uuid'); + $table->timestamp('last_reconciled_at')->nullable()->after('external_server_identifier'); + $table->timestamp('customer_notified_at')->nullable()->after('last_reconciled_at'); + $table->timestamp('product_stock_released_at')->nullable()->after('customer_notified_at'); + + $table->foreign('invoice_id') + ->references('id') + ->on('invoices') + ->nullOnDelete(); + $table->index(['invoice_id', 'status'], 'ptero_reservations_invoice_status_idx'); + $table->index( + ['status', 'next_provisioning_attempt_at'], + 'ptero_reservations_retry_idx' + ); + }); + + DB::table('ptero_resource_reservations') + ->whereNull('guaranteed_until') + ->update(['guaranteed_until' => DB::raw('expires_at')]); + + // Legacy terminal reservations were already handled by Paymenter's + // pre-durable cancellation paths. Mark them released so a repeated + // cancellation cannot return the same product unit twice. + DB::table('ptero_resource_reservations') + ->whereIn('status', ['expired', 'cancelled']) + ->whereNull('product_stock_released_at') + ->update(['product_stock_released_at' => now()]); + + Schema::create('ptero_capacity_scopes', function (Blueprint $table) { + $table->id(); + $table->string('panel_identity', 64); + $table->unsignedInteger('location_id'); + $table->timestamps(); + + $table->unique( + ['panel_identity', 'location_id'], + 'ptero_capacity_scopes_panel_location_unique' + ); + }); + + Schema::create('ptero_reservation_allocations', function (Blueprint $table) use ($driver) { + $table->id(); + $table->foreignId('reservation_id') + ->constrained('ptero_resource_reservations') + ->cascadeOnDelete(); + $table->string('panel_identity', 64); + $table->unsignedInteger('node_id'); + $table->unsignedBigInteger('allocation_id'); + $table->string('ip', 64)->nullable(); + $table->unsignedInteger('port'); + $table->string('environment_key', 191)->nullable(); + $table->boolean('is_primary')->default(false); + $table->timestamp('released_at')->nullable(); + $table->timestamps(); + + if ($driver !== 'sqlite') { + $table->unsignedBigInteger('active_allocation_id') + ->nullable() + ->storedAs('CASE WHEN released_at IS NULL THEN allocation_id ELSE NULL END'); + $table->unique( + ['panel_identity', 'active_allocation_id'], + 'ptero_reservation_allocations_active_unique' + ); + } + $table->index( + ['reservation_id', 'released_at'], + 'ptero_reservation_allocations_reservation_idx' + ); + $table->index( + ['node_id', 'released_at'], + 'ptero_reservation_allocations_node_idx' + ); + }); + + if ($driver === 'sqlite') { + // Partial indexes provide the same one-active-claim invariant + // without requiring SQLite generated-column support. + DB::statement( + 'CREATE UNIQUE INDEX ptero_reservation_allocations_active_unique ' + .'ON ptero_reservation_allocations (panel_identity, allocation_id) ' + .'WHERE released_at IS NULL' + ); + } + } + + public function down(): void + { + Schema::dropIfExists('ptero_reservation_allocations'); + Schema::dropIfExists('ptero_capacity_scopes'); + + DB::table('ptero_resource_reservations') + ->where('status', 'paid_committed') + ->update(['status' => 'pending']); + + Schema::table('ptero_resource_reservations', function (Blueprint $table) { + $table->dropForeign(['invoice_id']); + $table->dropIndex('ptero_reservations_invoice_status_idx'); + $table->dropIndex('ptero_reservations_retry_idx'); + $table->dropColumn([ + 'invoice_id', + 'guaranteed_until', + 'paid_committed_at', + 'provisioning_attempts', + 'last_provisioning_attempt_at', + 'next_provisioning_attempt_at', + 'failure_alerted_at', + 'cancellation_requested_at', + 'last_cancellation_error', + 'cancellation_failure_alerted_at', + 'external_server_id', + 'external_user_id', + 'external_server_uuid', + 'external_server_identifier', + 'last_reconciled_at', + 'customer_notified_at', + 'product_stock_released_at', + ]); + }); + + $driver = DB::getDriverName(); + if (in_array($driver, ['mysql', 'mariadb'], true)) { + DB::statement( + "ALTER TABLE ptero_resource_reservations MODIFY status " + . "ENUM('pending','confirmed','expired','cancelled') " + . "NOT NULL DEFAULT 'pending'" + ); + } elseif ($driver === 'sqlite') { + Schema::table( + 'ptero_resource_reservations', + fn (Blueprint $table) => $table + ->enum('status', [ + 'pending', + 'confirmed', + 'expired', + 'cancelled', + ]) + ->default('pending') + ->change() + ); + } + } +}; diff --git a/database/migrations/2026_07_26_000002_create_stock_foundation_tables.php b/database/migrations/2026_07_26_000002_create_stock_foundation_tables.php new file mode 100644 index 0000000..97684e5 --- /dev/null +++ b/database/migrations/2026_07_26_000002_create_stock_foundation_tables.php @@ -0,0 +1,42 @@ +id(); + $table->string('panel_identity', 64); + $table->string('node_uuid', 36); + $table->unsignedBigInteger('node_id'); + $table->unsignedInteger('location_id'); + $table->unsignedInteger('cpu_capacity_percent'); + $table->unsignedInteger('cpu_overcommit_bps')->default(10000); + $table->boolean('enabled')->default(true); + $table->timestamps(); + + $table->unique( + ['panel_identity', 'node_uuid'], + 'ptero_node_capacity_panel_uuid_unique' + ); + $table->index( + ['panel_identity', 'node_id'], + 'ptero_node_capacity_panel_id_index' + ); + $table->index( + ['panel_identity', 'location_id'], + 'ptero_node_capacity_panel_location_index' + ); + }); + + } + + public function down(): void + { + Schema::dropIfExists('ptero_node_capacity_policies'); + } +}; diff --git a/database/migrations/2026_07_26_000003_add_cpu_alert_thresholds.php b/database/migrations/2026_07_26_000003_add_cpu_alert_thresholds.php new file mode 100644 index 0000000..d3d0ddc --- /dev/null +++ b/database/migrations/2026_07_26_000003_add_cpu_alert_thresholds.php @@ -0,0 +1,63 @@ +unsignedTinyInteger('cpu_warning_threshold') + ->default(80); + } + if ($addCritical) { + $table->unsignedTinyInteger('cpu_critical_threshold') + ->default(95); + } + } + ); + } + + public function down(): void + { + if (! Schema::hasTable('ptero_alert_configs')) { + return; + } + + $columns = array_values(array_filter([ + Schema::hasColumn( + 'ptero_alert_configs', + 'cpu_warning_threshold' + ) ? 'cpu_warning_threshold' : null, + Schema::hasColumn( + 'ptero_alert_configs', + 'cpu_critical_threshold' + ) ? 'cpu_critical_threshold' : null, + ])); + Schema::table( + 'ptero_alert_configs', + function (Blueprint $table) use ($columns): void { + if ($columns !== []) { + $table->dropColumn($columns); + } + } + ); + } +}; diff --git a/database/migrations/2026_07_26_000005_widen_reservation_price.php b/database/migrations/2026_07_26_000005_widen_reservation_price.php new file mode 100644 index 0000000..0985390 --- /dev/null +++ b/database/migrations/2026_07_26_000005_widen_reservation_price.php @@ -0,0 +1,34 @@ +decimal('calculated_price', 17, 2)->change(); + }); + } + + public function down(): void + { + if ( + (float) DB::table('ptero_resource_reservations') + ->max('calculated_price') > 99_999_999.99 + ) { + throw new \RuntimeException( + 'Reservation prices no longer fit the legacy DECIMAL(10,2) column.' + ); + } + + Schema::table('ptero_resource_reservations', function (Blueprint $table) { + $table->decimal('calculated_price', 10, 2)->change(); + }); + } +}; diff --git a/database/migrations/2026_07_26_000010_encrypt_dynamic_pterodactyl_api_key.php b/database/migrations/2026_07_26_000010_encrypt_dynamic_pterodactyl_api_key.php new file mode 100644 index 0000000..9e8cbb9 --- /dev/null +++ b/database/migrations/2026_07_26_000010_encrypt_dynamic_pterodactyl_api_key.php @@ -0,0 +1,40 @@ +join('extensions', function ($join) { + $join->on('extensions.id', '=', 'settings.settingable_id') + ->where('settings.settingable_type', '=', Extension::class); + }) + ->where('extensions.extension', 'DynamicPterodactyl') + ->where('settings.key', 'pterodactyl_api_key') + ->where('settings.encrypted', false) + ->get(['settings.id', 'settings.value']); + + foreach ($settings as $setting) { + DB::table('settings') + ->where('id', $setting->id) + ->update([ + 'value' => $setting->value === null || $setting->value === '' + ? $setting->value + : Crypt::encryptString((string) $setting->value), + 'encrypted' => true, + 'updated_at' => now(), + ]); + } + } + + public function down(): void + { + // Intentionally irreversible: a rollback must never restore an API key + // to plaintext storage. + } +}; diff --git a/database/migrations/2026_07_26_000020_add_upgrade_identity_to_ptero_reservations.php b/database/migrations/2026_07_26_000020_add_upgrade_identity_to_ptero_reservations.php new file mode 100644 index 0000000..c4d8f28 --- /dev/null +++ b/database/migrations/2026_07_26_000020_add_upgrade_identity_to_ptero_reservations.php @@ -0,0 +1,97 @@ +string('purpose', 24)->default('checkout')->after('id'); + $table->unsignedInteger('reserved_memory')->default(0)->after('memory'); + $table->unsignedInteger('reserved_cpu')->default(0)->after('cpu'); + $table->unsignedBigInteger('reserved_disk')->default(0)->after('disk'); + $table->unsignedBigInteger('service_upgrade_id')->nullable()->after('service_id'); + // Keep the partial-unique source separate from the nullable FK. + // MariaDB rejects generated columns derived from SET NULL FKs. + $table->unsignedBigInteger('upgrade_guard_id')->nullable()->after('service_upgrade_id'); + if ($driver !== 'sqlite') { + $table->unsignedBigInteger('active_upgrade_id') + ->nullable() + ->storedAs( + "CASE WHEN purpose = 'upgrade' AND " + ."(status = 'pending' OR status = 'paid_committed') " + .'THEN upgrade_guard_id ELSE NULL END' + ) + ->after('upgrade_guard_id'); + } + + $table->foreign('service_upgrade_id') + ->references('id') + ->on('service_upgrades') + ->restrictOnDelete(); + if ($driver !== 'sqlite') { + $table->unique( + 'active_upgrade_id', + 'ptero_reservations_active_upgrade_unique' + ); + } + $table->index( + ['purpose', 'status'], + 'ptero_reservations_purpose_status_idx' + ); + $table->index( + 'service_upgrade_id', + 'ptero_reservations_service_upgrade_idx' + ); + }); + + if ($driver === 'sqlite') { + DB::statement( + 'CREATE UNIQUE INDEX ptero_reservations_active_upgrade_unique ' + .'ON ptero_resource_reservations (upgrade_guard_id) ' + ."WHERE purpose = 'upgrade' " + ."AND status IN ('pending', 'paid_committed') " + .'AND upgrade_guard_id IS NOT NULL' + ); + } + } + + public function down(): void + { + $driver = DB::getDriverName(); + if ($driver === 'sqlite') { + DB::statement( + 'DROP INDEX IF EXISTS ptero_reservations_active_upgrade_unique' + ); + } + + Schema::table('ptero_resource_reservations', function (Blueprint $table) use ($driver) { + $table->dropForeign(['service_upgrade_id']); + if ($driver !== 'sqlite') { + $table->dropUnique( + 'ptero_reservations_active_upgrade_unique' + ); + } + $table->dropIndex('ptero_reservations_purpose_status_idx'); + $table->dropIndex('ptero_reservations_service_upgrade_idx'); + $columns = [ + 'upgrade_guard_id', + 'service_upgrade_id', + 'reserved_memory', + 'reserved_cpu', + 'reserved_disk', + 'purpose', + ]; + if ($driver !== 'sqlite') { + array_unshift($columns, 'active_upgrade_id'); + } + $table->dropColumn($columns); + }); + } +}; diff --git a/database/migrations/2026_07_26_000030_enforce_one_checkout_commitment_per_service.php b/database/migrations/2026_07_26_000030_enforce_one_checkout_commitment_per_service.php new file mode 100644 index 0000000..3782ab2 --- /dev/null +++ b/database/migrations/2026_07_26_000030_enforce_one_checkout_commitment_per_service.php @@ -0,0 +1,151 @@ +unsignedBigInteger('service_guard_id')->nullable()->after('service_id'); + }); + + DB::table('ptero_resource_reservations') + ->whereNotNull('service_id') + ->whereNull('service_guard_id') + ->update(['service_guard_id' => DB::raw('service_id')]); + + $activeStatuses = ['pending', 'paid_committed', 'confirmed']; + $duplicateGroups = DB::table('ptero_resource_reservations') + ->where('purpose', 'checkout') + ->whereNotNull('service_id') + ->whereIn('status', $activeStatuses) + ->get() + ->groupBy('service_id') + ->filter(fn ($rows) => $rows->count() > 1); + + foreach ($duplicateGroups as $serviceId => $rows) { + $externalIdentities = $rows + ->where('status', 'confirmed') + ->filter(fn ($row) => $row->external_server_id !== null || $row->external_server_uuid !== null) + ->map(fn ($row) => ($row->external_server_id ?? 'unknown') + .':' . ($row->external_server_uuid ?? 'unknown')) + ->unique() + ->values(); + if ($externalIdentities->count() > 1) { + throw new \RuntimeException( + "Service {$serviceId} has conflicting confirmed Pterodactyl identities; " + .'resolve them manually before running the durable-fulfillment migration.' + ); + } + + $ranked = $rows->sort(function ($left, $right): int { + $rank = static function ($row): int { + if ( + $row->status === 'confirmed' + && $row->external_server_id !== null + && $row->external_server_uuid !== null + ) { + return 4; + } + + return match ($row->status) { + 'confirmed' => 3, + 'paid_committed' => 2, + 'pending' => 1, + default => 0, + }; + }; + $status = $rank($right) <=> $rank($left); + if ($status !== 0) { + return $status; + } + + $leftFingerprint = $left->configuration_fingerprint !== null ? 1 : 0; + $rightFingerprint = $right->configuration_fingerprint !== null ? 1 : 0; + if ($leftFingerprint !== $rightFingerprint) { + return $rightFingerprint <=> $leftFingerprint; + } + + return (int) $right->id <=> (int) $left->id; + })->values(); + $retiredIds = $ranked->slice(1)->pluck('id'); + if ($retiredIds->isEmpty()) { + continue; + } + + DB::table('ptero_resource_reservations') + ->whereIn('id', $retiredIds) + ->update([ + 'status' => 'cancelled', + 'admin_notes' => 'Retired duplicate service commitment during durable-fulfillment migration.', + 'provisioning_started_at' => null, + 'provisioning_lease_id' => null, + 'updated_at' => now(), + ]); + DB::table('ptero_reservation_allocations') + ->whereIn('reservation_id', $retiredIds) + ->whereNull('released_at') + ->update([ + 'released_at' => now(), + 'updated_at' => now(), + ]); + } + + if ($driver === 'sqlite') { + DB::statement( + 'CREATE UNIQUE INDEX ptero_reservations_active_checkout_service_unique ' + .'ON ptero_resource_reservations (service_guard_id) ' + ."WHERE purpose = 'checkout' " + ."AND status IN ('pending', 'paid_committed', 'confirmed') " + .'AND service_guard_id IS NOT NULL' + ); + } else { + Schema::table('ptero_resource_reservations', function (Blueprint $table) { + $table + ->unsignedBigInteger('active_checkout_service_id') + ->nullable() + ->storedAs( + "CASE WHEN purpose = 'checkout' AND " + ."(status = 'pending' OR status = 'paid_committed' OR status = 'confirmed') " + .'THEN service_guard_id ELSE NULL END' + ) + ->after('service_guard_id'); + $table->unique( + 'active_checkout_service_id', + 'ptero_reservations_active_checkout_service_unique' + ); + }); + } + } + + public function down(): void + { + $driver = DB::getDriverName(); + if ($driver === 'sqlite') { + DB::statement( + 'DROP INDEX IF EXISTS ptero_reservations_active_checkout_service_unique' + ); + Schema::table( + 'ptero_resource_reservations', + fn (Blueprint $table) => + $table->dropColumn('service_guard_id') + ); + } else { + Schema::table('ptero_resource_reservations', function (Blueprint $table) { + $table->dropUnique('ptero_reservations_active_checkout_service_unique'); + $table->dropColumn([ + 'active_checkout_service_id', + 'service_guard_id', + ]); + }); + } + } +}; diff --git a/migration-readiness.php b/migration-readiness.php new file mode 100644 index 0000000..4ba87a2 --- /dev/null +++ b/migration-readiness.php @@ -0,0 +1,671 @@ + + * }> + */ + public function blockers(): array + { + if (! Schema::hasTable('ptero_resource_reservations')) { + return []; + } + + $requiredColumns = [ + 'purpose', + 'configuration_fingerprint', + 'configuration_payload', + 'external_server_id', + 'external_user_id', + 'external_server_uuid', + 'external_server_identifier', + ]; + foreach ($requiredColumns as $column) { + if (! Schema::hasColumn('ptero_resource_reservations', $column)) { + return [[ + 'reservation_id' => 0, + 'service_id' => null, + 'purpose' => 'schema', + 'missing' => ["column:{$column}"], + ]]; + } + } + + return DB::table('ptero_resource_reservations') + ->where(function ($query): void { + $query->where(function ($query): void { + $query->where('purpose', 'checkout') + ->whereIn('status', [ + 'pending', + 'paid_committed', + 'confirmed', + ]) + ->whereNotNull('service_id'); + })->orWhere(function ($query): void { + $query->where('purpose', 'upgrade') + ->whereIn('status', ['pending', 'paid_committed']); + }); + }) + ->orderBy('id') + ->get() + ->map(function (object $reservation): array { + $missing = $reservation->purpose === 'upgrade' + ? $this->missingUpgradeIdentity($reservation) + : $this->missingCheckoutIdentity($reservation); + + return [ + 'reservation_id' => (int) $reservation->id, + 'service_id' => $reservation->service_id !== null + ? (int) $reservation->service_id + : null, + 'purpose' => (string) $reservation->purpose, + 'missing' => $missing, + ]; + }) + ->filter(fn (array $row): bool => $row['missing'] !== []) + ->values() + ->all(); + } + + public function assertReady(): void + { + $blockers = $this->blockers(); + if ($blockers === []) { + return; + } + + $shown = array_slice($blockers, 0, 25); + $details = array_map( + fn (array $row): string => sprintf( + 'reservation #%d%s [%s]: %s', + $row['reservation_id'], + $row['service_id'] !== null + ? " / service #{$row['service_id']}" + : '', + $row['purpose'], + implode(', ', $row['missing']) + ), + $shown + ); + if (count($blockers) > count($shown)) { + $details[] = sprintf( + 'and %d more unresolved row(s)', + count($blockers) - count($shown) + ); + } + + throw new \RuntimeException( + 'Dynamic Pterodactyl cannot finish upgrading because legacy ' + .'reservations lack immutable fulfillment identity: ' + .implode('; ', $details) + .'. Reconstruct the exact signed order configuration for every ' + .'bound unpaid commitment. For provisioned services, also verify ' + .'and import the exact numeric server/user IDs, UUID, identifier, ' + .'panel, node, nest, and egg from Pterodactyl and auditable order ' + .'records; never infer authority from an external-ID lookup or ' + .'current product settings. Then rerun ' + .'php artisan app:extension:migrate other DynamicPterodactyl --force.' + ); + } + + /** + * @return list + */ + private function missingCheckoutIdentity(object $reservation): array + { + $missing = $reservation->status === 'confirmed' + ? $this->missingCommonRemoteIdentity($reservation) + : []; + foreach ([ + 'server_extension_id', + 'service_id', + 'user_id', + 'product_id', + 'plan_id', + ] as $field) { + $this->requirePositive( + $reservation->{$field}, + $field, + $missing + ); + } + $payload = $this->decodedPayload($reservation, $missing); + if ($payload === null) { + return array_values(array_unique($missing)); + } + + $fingerprint = $reservation->configuration_fingerprint; + if ( + ! is_string($fingerprint) + || preg_match('/^[a-f0-9]{64}$/D', $fingerprint) !== 1 + || ! hash_equals( + $fingerprint, + $this->fingerprint($payload) + ) + ) { + $missing[] = 'valid configuration_fingerprint'; + } + $service = Service::query()->find($reservation->service_id); + if ($service === null) { + $missing[] = 'service'; + } elseif (! $this->checkoutPayloadMatchesService( + $payload, + $reservation, + $service + )) { + $missing[] = 'signed checkout/service identity agreement'; + } + + $provisioning = $payload['provisioning_identity'] ?? null; + if (! is_array($provisioning)) { + $missing[] = 'provisioning_identity'; + + return array_values(array_unique($missing)); + } + $this->requirePositive( + $provisioning['nest_id'] ?? null, + 'provisioning_identity.nest_id', + $missing + ); + $this->requirePositive( + $provisioning['egg_id'] ?? null, + 'provisioning_identity.egg_id', + $missing + ); + $expectedUserExternalId = $reservation->user_id !== null + ? "paymenter-user-{$reservation->user_id}" + : null; + if ( + $expectedUserExternalId === null + || ! is_string($provisioning['user_external_id'] ?? null) + || ! hash_equals( + $expectedUserExternalId, + $provisioning['user_external_id'] + ) + ) { + $missing[] = 'provisioning_identity.user_external_id'; + } + foreach ([ + 'panel_identity' => $reservation->panel_identity, + 'node_id' => $reservation->node_id, + 'customer_id' => $reservation->user_id, + 'product_id' => $reservation->product_id, + 'plan_id' => $reservation->plan_id, + ] as $field => $expected) { + $actual = data_get($payload, $field); + if ( + $field === 'panel_identity' + ? ! is_string($actual) + || ! is_string($expected) + || ! hash_equals($expected, $actual) + : StrictInteger::parse($actual) === null + || (int) $actual !== (int) $expected + ) { + $missing[] = "configuration_payload.{$field}"; + } + } + if ($reservation->status !== 'confirmed') { + $this->requireActiveAllocationClaims( + $reservation, + $payload, + $missing + ); + } + + return array_values(array_unique($missing)); + } + + /** + * A bound checkout is not migratable unless the allocation rows still + * materialize the exact signed port claims. Otherwise a paid invoice could + * become durable before provisioning discovers the drift. + * + * @param array $payload + * @param list $missing + */ + private function requireActiveAllocationClaims( + object $reservation, + array $payload, + array &$missing + ): void { + if (! Schema::hasTable('ptero_reservation_allocations')) { + $missing[] = 'active signed allocation claims'; + + return; + } + + $allocations = $payload['allocations'] ?? null; + if (! is_array($allocations) || $allocations === []) { + $missing[] = 'active signed allocation claims'; + + return; + } + + $expected = []; + foreach ($allocations as $allocation) { + if (! is_array($allocation)) { + $missing[] = 'active signed allocation claims'; + + return; + } + $allocationId = StrictInteger::parse( + $allocation['allocation_id'] ?? null + ); + $port = StrictInteger::parse($allocation['port'] ?? null); + if ( + $allocationId === null + || $allocationId <= 0 + || $port === null + || $port <= 0 + || $port > 65535 + ) { + $missing[] = 'active signed allocation claims'; + + return; + } + $expected[] = [ + 'panel_identity' => (string) $reservation->panel_identity, + 'node_id' => (int) $reservation->node_id, + 'allocation_id' => $allocationId, + 'ip' => (string) ($allocation['ip'] ?? ''), + 'port' => $port, + 'environment_key' => + $allocation['environment_key'] ?? null, + 'is_primary' => + (bool) ($allocation['is_primary'] ?? false), + ]; + } + usort( + $expected, + fn (array $left, array $right): int => + $left['allocation_id'] <=> $right['allocation_id'] + ); + + $claims = DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservation->id) + ->get(); + $actual = $claims + ->map(fn (object $allocation): array => [ + 'panel_identity' => (string) $allocation->panel_identity, + 'node_id' => (int) $allocation->node_id, + 'allocation_id' => (int) $allocation->allocation_id, + 'ip' => (string) ($allocation->ip ?? ''), + 'port' => (int) $allocation->port, + 'environment_key' => $allocation->environment_key, + 'is_primary' => (bool) $allocation->is_primary, + ]) + ->sortBy('allocation_id') + ->values() + ->all(); + + if ( + $expected !== $actual + || collect($actual)->where('is_primary', true)->count() !== 1 + || $claims->contains( + fn (object $allocation): bool => + $allocation->released_at !== null + ) + ) { + $missing[] = 'active signed allocation claims'; + } + } + + /** + * Reproduce the checkout identity proof locally so an upload never resolves + * a readiness service class that may already be loaded from the old tree. + * + * @param array $payload + */ + private function checkoutPayloadMatchesService( + array $payload, + object $reservation, + Service $service + ): bool { + $provisioning = $payload['provisioning_identity'] ?? null; + $nestId = is_array($provisioning) + ? StrictInteger::parse($provisioning['nest_id'] ?? null) + : null; + $eggId = is_array($provisioning) + ? StrictInteger::parse($provisioning['egg_id'] ?? null) + : null; + + return (int) $reservation->service_id === (int) $service->id + && (int) $reservation->user_id === (int) $service->user_id + && (int) $reservation->product_id === (int) $service->product_id + && (int) $reservation->plan_id === (int) $service->plan_id + && (int) $reservation->quantity === (int) $service->quantity + && strtoupper((string) $reservation->currency_code) + === strtoupper((string) $service->currency_code) + && (int) ($payload['customer_id'] ?? 0) + === (int) $reservation->user_id + && (int) ($payload['server_extension_id'] ?? 0) + === (int) $reservation->server_extension_id + && (string) ($payload['panel_identity'] ?? '') + === (string) $reservation->panel_identity + && (int) ($payload['product_id'] ?? 0) + === (int) $reservation->product_id + && (int) ($payload['plan_id'] ?? 0) + === (int) $reservation->plan_id + && (int) ($payload['quantity'] ?? 0) + === (int) $reservation->quantity + && strtoupper((string) ($payload['currency_code'] ?? '')) + === strtoupper((string) $reservation->currency_code) + && (int) data_get($payload, 'resources.memory', 0) + === (int) $reservation->memory + && (int) data_get($payload, 'resources.cpu', 0) + === (int) $reservation->cpu + && (int) data_get($payload, 'resources.disk', 0) + === (int) $reservation->disk + && (int) ($payload['location_id'] ?? 0) + === (int) $reservation->location_id + && (int) ($payload['node_id'] ?? 0) + === (int) $reservation->node_id + && $nestId !== null + && $nestId > 0 + && $eggId !== null + && $eggId > 0 + && is_string($provisioning['user_external_id'] ?? null) + && hash_equals( + "paymenter-user-{$service->user_id}", + $provisioning['user_external_id'] + ) + && is_string($provisioning['user_email'] ?? null) + && trim($provisioning['user_email']) !== ''; + } + + /** + * @param array $payload + */ + private function fingerprint(array $payload): string + { + return hash('sha256', json_encode( + $this->canonicalize($payload), + JSON_THROW_ON_ERROR + | JSON_PRESERVE_ZERO_FRACTION + | JSON_UNESCAPED_SLASHES + )); + } + + /** + * @param array $value + * @return array + */ + private function canonicalize(array $value): array + { + foreach ($value as $key => $item) { + if (is_array($item)) { + $value[$key] = $this->canonicalize($item); + } + } + if (! array_is_list($value)) { + ksort($value); + } + + return $value; + } + + /** + * @return list + */ + private function missingUpgradeIdentity(object $reservation): array + { + $missing = $this->missingCommonRemoteIdentity($reservation); + $payload = $this->decodedPayload($reservation, $missing); + if ($payload === null) { + return array_values(array_unique($missing)); + } + + foreach ([ + 'service_upgrade_id', + 'node_id', + 'location_id', + 'external_server_id', + 'external_user_id', + 'nest_id', + 'egg_id', + 'allocation_id', + ] as $field) { + $this->requirePositive( + $payload[$field] ?? null, + "configuration_payload.{$field}", + $missing + ); + } + foreach ([ + 'external_server_uuid', + 'external_server_identifier', + 'external_server_external_id', + 'user_external_id', + ] as $field) { + if ( + ! is_string($payload[$field] ?? null) + || trim($payload[$field]) === '' + ) { + $missing[] = "configuration_payload.{$field}"; + } + } + if ( + is_string($payload['external_server_uuid'] ?? null) + && ! Str::isUuid($payload['external_server_uuid']) + ) { + $missing[] = 'configuration_payload.external_server_uuid'; + } + foreach (['source', 'target', 'delta', 'preserved_build'] as $field) { + if (! is_array($payload[$field] ?? null)) { + $missing[] = "configuration_payload.{$field}"; + } + } + $allocationIds = $payload['assigned_allocation_ids'] ?? null; + if ( + ! is_array($allocationIds) + || $allocationIds === [] + || collect($allocationIds)->contains( + fn ($id): bool => StrictInteger::parse($id) === null + || (int) $id <= 0 + ) + ) { + $missing[] = 'configuration_payload.assigned_allocation_ids'; + } + if ( + (string) ($payload['panel_identity'] ?? '') + !== (string) $reservation->panel_identity + || (int) ($payload['node_id'] ?? 0) + !== (int) $reservation->node_id + || (int) ($payload['external_server_id'] ?? 0) + !== (int) $reservation->external_server_id + || (int) ($payload['external_user_id'] ?? 0) + !== (int) $reservation->external_user_id + || (string) ($payload['external_server_uuid'] ?? '') + !== (string) $reservation->external_server_uuid + || (string) ($payload['external_server_identifier'] ?? '') + !== (string) $reservation->external_server_identifier + ) { + $missing[] = 'payload/row identity agreement'; + } + if ( + ! is_string($reservation->configuration_fingerprint) + || preg_match( + '/^[a-f0-9]{64}$/D', + $reservation->configuration_fingerprint + ) !== 1 + ) { + $missing[] = 'configuration_fingerprint'; + } elseif (! $this->upgradeFingerprintMatches( + $reservation, + $payload + )) { + $missing[] = 'valid configuration_fingerprint'; + } + + return array_values(array_unique($missing)); + } + + /** + * Prove the active upgrade payload against the billing and before/after + * fingerprints captured on its ServiceUpgrade row. + * + * @param array $payload + */ + private function upgradeFingerprintMatches( + object $reservation, + array $payload + ): bool { + $upgradeId = StrictInteger::parse( + $reservation->service_upgrade_id + ); + if ($upgradeId === null || $upgradeId <= 0) { + return false; + } + $upgrade = DB::table('service_upgrades')->find($upgradeId); + if ($upgrade === null) { + return false; + } + + try { + $expected = hash('sha256', json_encode([ + 'upgrade_id' => $upgradeId, + 'source_fingerprint' => (string) $upgrade->source_fingerprint, + 'target_fingerprint' => (string) $upgrade->target_fingerprint, + 'panel_identity' => $payload['panel_identity'] ?? null, + 'node_id' => $payload['node_id'] ?? null, + 'location_id' => $payload['location_id'] ?? null, + 'external_server_id' => + $payload['external_server_id'] ?? null, + 'external_server_uuid' => + $payload['external_server_uuid'] ?? null, + 'external_server_identifier' => + $payload['external_server_identifier'] ?? null, + 'external_server_external_id' => + $payload['external_server_external_id'] ?? null, + 'external_user_id' => + $payload['external_user_id'] ?? null, + 'user_external_id' => + $payload['user_external_id'] ?? null, + 'user_email' => $payload['user_email'] ?? null, + 'nest_id' => $payload['nest_id'] ?? null, + 'egg_id' => $payload['egg_id'] ?? null, + 'preserved_build' => + $payload['preserved_build'] ?? null, + 'allocation_id' => $payload['allocation_id'] ?? null, + 'assigned_allocation_ids' => + $payload['assigned_allocation_ids'] ?? null, + 'source' => $payload['source'] ?? null, + 'target' => $payload['target'] ?? null, + 'delta' => $payload['delta'] ?? null, + 'quoted_amount' => (string) $upgrade->quoted_amount, + 'currency_code' => strtoupper( + (string) $upgrade->currency_code + ), + ], JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES)); + } catch (\JsonException) { + return false; + } + + return hash_equals( + (string) $reservation->configuration_fingerprint, + $expected + ); + } + + /** + * @param list $missing + * @return array|null + */ + private function decodedPayload( + object $reservation, + array &$missing + ): ?array { + try { + $payload = json_decode( + (string) $reservation->configuration_payload, + true, + 512, + JSON_THROW_ON_ERROR + ); + } catch (\JsonException) { + $payload = null; + } + if (! is_array($payload)) { + $missing[] = 'configuration_payload'; + + return null; + } + + return $payload; + } + + /** + * @return list + */ + private function missingCommonRemoteIdentity(object $reservation): array + { + $missing = []; + $this->requirePositive( + $reservation->external_server_id, + 'external_server_id', + $missing + ); + $this->requirePositive( + $reservation->external_user_id, + 'external_user_id', + $missing + ); + if ( + ! is_string($reservation->external_server_uuid) + || ! Str::isUuid($reservation->external_server_uuid) + ) { + $missing[] = 'external_server_uuid'; + } + if ( + ! is_string($reservation->external_server_identifier) + || trim($reservation->external_server_identifier) === '' + ) { + $missing[] = 'external_server_identifier'; + } + if ( + ! is_string($reservation->panel_identity) + || preg_match('/^[a-f0-9]{64}$/D', $reservation->panel_identity) + !== 1 + ) { + $missing[] = 'panel_identity'; + } + $this->requirePositive( + $reservation->node_id, + 'node_id', + $missing + ); + + return $missing; + } + + /** + * @param list $missing + */ + private function requirePositive( + mixed $value, + string $field, + array &$missing + ): void { + $parsed = StrictInteger::parse($value); + if ($parsed === null || $parsed <= 0) { + $missing[] = $field; + } + } +} diff --git a/routes/api.php b/routes/api.php index 54f734c..ecf881a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -8,16 +8,22 @@ use Illuminate\Support\Facades\Route; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\AvailabilityController; -use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\PricingController; +use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\ResourceQuoteController; +use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\UpgradeQuoteController; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\Admin\AdminCapacityController; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\Admin\AdminReservationController; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Middleware\EnsureUserIsAdmin; -// Availability and pricing — throttled (30 req/min) to protect Pterodactyl API budget +// Customer stock quote — guest-safe, CSRF-protected, and intentionally does +// not expose node identity or other infrastructure detail. +Route::prefix('api/dynamic-pterodactyl')->middleware(['web', 'throttle:30,1'])->group(function () { + Route::post('/products/{product}/resource-quote', ResourceQuoteController::class) + ->whereNumber('product'); +}); + +// Existing-service stock quotes are authenticated and customer-owned. Route::prefix('api/dynamic-pterodactyl')->middleware(['web', 'auth', 'throttle:30,1'])->group(function () { - Route::get('/availability/{locationId}', [AvailabilityController::class, 'getByLocation']); - Route::post('/pricing/calculate', [PricingController::class, 'calculate']); - Route::get('/pricing/config/{productId}', [PricingController::class, 'getConfig']); + Route::post('/services/{service}/upgrade-quote', UpgradeQuoteController::class); }); // Admin routes — session-based, gated by non-null role (matches User::canAccessPanel) diff --git a/tests/AGENTS.md b/tests/AGENTS.md index f96157c..abe2a7b 100644 --- a/tests/AGENTS.md +++ b/tests/AGENTS.md @@ -58,4 +58,4 @@ Largest files are `Unit/ReservationServiceTest.php` and `Unit/AlertServiceTest.p - Do not broaden the database guard beyond `paymenter_test`, `:memory:`, or the internally generated `:temporary:` workflow. Never accept a caller-supplied SQLite path or named-memory URI. - Do not add live Pterodactyl network calls; fake panel HTTP explicitly and prevent strays when testing capacity reads. - Do not expose or assert full reservation tokens in audit payloads; assert `token_prefix` behavior. -- Current direct coverage gaps to watch: full cart-listener database integration, `PricingController::getConfig()`, and `AuditLogService` retrieval methods. +- Current direct coverage gaps to watch: full cart-listener database integration and `AuditLogService` retrieval methods. diff --git a/tests/Feature/AdminApiTest.php b/tests/Feature/AdminApiTest.php index 3e5ad6d..4a3d5b7 100644 --- a/tests/Feature/AdminApiTest.php +++ b/tests/Feature/AdminApiTest.php @@ -101,6 +101,26 @@ public function test_admin_filters_by_status(): void } } + public function test_admin_can_filter_durable_paid_commitments(): void + { + $admin = $this->makeAdminUser(); + $this->makeReservation(['status' => 'paid_committed']); + $this->makeReservation(['status' => 'pending']); + + $response = $this->actingAs($admin) + ->withSession($this->loginUser($admin)) + ->getJson( + '/api/dynamic-pterodactyl/admin/reservations?status=paid_committed' + ); + + $response->assertOk(); + $this->assertCount(1, $response->json('data.data')); + $this->assertSame( + 'paid_committed', + $response->json('data.data.0.status') + ); + } + public function test_admin_cancels_reservation_with_reason(): void { $admin = $this->makeAdminUser(); diff --git a/tests/Feature/AvailabilityApiTest.php b/tests/Feature/AvailabilityApiTest.php index d52bcb8..eecc62f 100644 --- a/tests/Feature/AvailabilityApiTest.php +++ b/tests/Feature/AvailabilityApiTest.php @@ -4,9 +4,6 @@ use App\Models\User; use Illuminate\Foundation\Testing\DatabaseTransactions; -use Mockery; -use Paymenter\Extensions\Others\DynamicPterodactyl\Services\NodeSelectionService; -use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceCalculationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; class AvailabilityApiTest extends LaravelTestCase @@ -20,115 +17,30 @@ protected function setUp(): void require __DIR__ . '/../../routes/api.php'; } - public function test_cpu_is_explicitly_not_enforced_as_capacity(): void + public function test_legacy_independent_maximum_availability_route_is_removed(): void { /** @var User $user */ $user = User::factory()->create(); - $this->bindAvailabilityServices([ - 'memory' => 1000, - 'cpu' => 0, - 'disk' => 1000, - ]); - - $response = $this->actingAs($user) + $this->actingAs($user) ->withSession($this->loginUser($user)) - ->getJson('/api/dynamic-pterodactyl/availability/1'); - - $response->assertOk()->assertJson([ - 'success' => true, - 'data' => [ - 'has_capacity' => true, - 'resource_capacity' => [ - 'memory' => true, - 'cpu' => null, - 'disk' => true, - ], - 'cpu_capacity_enforced' => false, - ], - ]); - - $this->assertArrayNotHasKey('nodes', $response->json('data'), - 'Customer availability response must not expose node-level data'); + ->getJson('/api/dynamic-pterodactyl/availability/1') + ->assertNotFound(); } - public function test_has_capacity_true_when_all_resources_positive(): void + public function test_legacy_extension_pricing_routes_are_removed(): void { /** @var User $user */ $user = User::factory()->create(); - $this->bindAvailabilityServices([ - 'memory' => 1000, - 'cpu' => 100, - 'disk' => 1000, - ]); - - $response = $this->actingAs($user) + $this->actingAs($user) ->withSession($this->loginUser($user)) - ->getJson('/api/dynamic-pterodactyl/availability/1'); - - $response->assertOk()->assertJson([ - 'success' => true, - 'data' => [ - 'has_capacity' => true, - 'resource_capacity' => [ - 'memory' => true, - 'cpu' => null, - 'disk' => true, - ], - 'cpu_capacity_enforced' => false, - ], - ]); - - $this->assertArrayNotHasKey('nodes', $response->json('data'), - 'Customer availability response must not expose node-level data'); - } - - public function test_customer_failure_response_does_not_expose_internal_exception(): void - { - /** @var User $user */ - $user = User::factory()->create(); - - $resourceService = Mockery::mock(ResourceCalculationService::class); - $resourceService->shouldReceive('getLocationAvailability') - ->once() - ->with(1) - ->andThrow(new \RuntimeException('panel-internal-host:8080 failed')); - $this->app->instance(ResourceCalculationService::class, $resourceService); - - $nodeService = Mockery::mock(NodeSelectionService::class); - $nodeService->shouldNotReceive('getMaxAvailable'); - $this->app->instance(NodeSelectionService::class, $nodeService); - - $response = $this->actingAs($user)->getJson('/api/dynamic-pterodactyl/availability/1'); - - $response->assertStatus(500)->assertExactJson([ - 'success' => false, - 'message' => 'Failed to fetch availability', - ]); - $this->assertStringNotContainsString('panel-internal-host', $response->getContent()); - } - - private function bindAvailabilityServices(array $maxAvailable): void - { - $locationData = [ - 'location_id' => 1, - 'nodes' => [['node_id' => 1, 'name' => 'Node 1']], - 'max_available' => $maxAvailable, - ]; + ->postJson('/api/dynamic-pterodactyl/pricing/calculate', []) + ->assertNotFound(); - $nodeService = Mockery::mock(NodeSelectionService::class); - $nodeService->shouldReceive('getMaxAvailable') - ->once() - ->with(1, $locationData) - ->andReturn($maxAvailable); - $this->app->instance(NodeSelectionService::class, $nodeService); - - $resourceService = Mockery::mock(ResourceCalculationService::class); - $resourceService->shouldReceive('getLocationAvailability') - ->once() - ->with(1) - ->andReturn($locationData); - $this->app->instance(ResourceCalculationService::class, $resourceService); + $this->actingAs($user) + ->withSession($this->loginUser($user)) + ->getJson('/api/dynamic-pterodactyl/pricing/config/1') + ->assertNotFound(); } } diff --git a/tests/Feature/LegacyReservationReadinessTest.php b/tests/Feature/LegacyReservationReadinessTest.php new file mode 100644 index 0000000..cfacc40 --- /dev/null +++ b/tests/Feature/LegacyReservationReadinessTest.php @@ -0,0 +1,303 @@ +assertReady(); + + $this->addToAssertionCount(1); + } + + public function test_confirmed_legacy_checkout_reports_actionable_identity_fields(): void + { + $service = $this->service(); + $reservationId = $this->insertReservation($service, [ + 'status' => 'confirmed', + 'configuration_fingerprint' => null, + 'configuration_payload' => null, + ]); + + try { + (new LegacyReservationReadinessService)->assertReady(); + $this->fail('Expected legacy confirmed identity to block migration.'); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + "reservation #{$reservationId} / service #{$service->id}", + $exception->getMessage() + ); + $this->assertStringContainsString( + 'external_server_uuid', + $exception->getMessage() + ); + $this->assertStringContainsString( + 'configuration_payload', + $exception->getMessage() + ); + $this->assertStringContainsString( + 'never infer them', + $exception->getMessage() + ); + } + } + + public function test_active_upgrade_without_immutable_identity_blocks_migration(): void + { + $service = $this->service(); + $reservationId = $this->insertReservation($service, [ + 'purpose' => 'upgrade', + 'status' => 'paid_committed', + 'configuration_fingerprint' => str_repeat('a', 64), + 'configuration_payload' => json_encode([], JSON_THROW_ON_ERROR), + ]); + + $blockers = (new LegacyReservationReadinessService)->blockers(); + + $this->assertSame($reservationId, $blockers[0]['reservation_id']); + $this->assertSame('upgrade', $blockers[0]['purpose']); + $this->assertContains( + 'configuration_payload.external_server_id', + $blockers[0]['missing'] + ); + } + + public function test_bound_unpaid_checkout_without_signed_snapshot_blocks_migration(): void + { + $service = $this->service(); + $reservationId = $this->insertReservation($service, [ + 'status' => 'pending', + 'configuration_fingerprint' => null, + 'configuration_payload' => null, + 'external_server_id' => null, + 'external_user_id' => null, + 'external_server_uuid' => null, + 'external_server_identifier' => null, + ]); + + $blockers = (new LegacyReservationReadinessService)->blockers(); + + $this->assertSame($reservationId, $blockers[0]['reservation_id']); + $this->assertContains( + 'configuration_payload', + $blockers[0]['missing'] + ); + $this->assertNotContains( + 'external_server_id', + $blockers[0]['missing'] + ); + } + + public function test_complete_signed_checkout_identity_passes_gate(): void + { + $service = $this->service(); + $panel = hash('sha256', 'https://panel.example.com'); + $payload = [ + 'customer_id' => $service->user_id, + 'server_extension_id' => 41, + 'panel_identity' => $panel, + 'product_id' => $service->product_id, + 'plan_id' => $service->plan_id, + 'quantity' => 1, + 'currency_code' => 'USD', + 'resources' => [ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + ], + 'location_id' => 3, + 'node_id' => 7, + 'provisioning_identity' => [ + 'nest_id' => 1, + 'egg_id' => 2, + 'user_external_id' => + "paymenter-user-{$service->user_id}", + 'user_email' => (string) $service->user->email, + ], + 'allocations' => [[ + 'allocation_id' => 7001, + 'ip' => '192.0.2.10', + 'port' => 25565, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ]], + ]; + $fingerprint = (new ReservationConfigurationService) + ->fingerprint($payload); + $this->insertReservation($service, [ + 'status' => 'confirmed', + 'server_extension_id' => 41, + 'panel_identity' => $panel, + 'configuration_fingerprint' => $fingerprint, + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + 'external_server_id' => 71, + 'external_user_id' => 44, + 'external_server_uuid' => + '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', + 'external_server_identifier' => 'server-71', + ]); + + (new LegacyReservationReadinessService)->assertReady(); + + $this->addToAssertionCount(1); + } + + public function test_bound_unpaid_checkout_requires_materialized_allocation_claims(): void + { + $service = $this->service(); + $panel = hash('sha256', 'https://panel.example.com'); + $payload = [ + 'customer_id' => $service->user_id, + 'server_extension_id' => 41, + 'panel_identity' => $panel, + 'product_id' => $service->product_id, + 'plan_id' => $service->plan_id, + 'quantity' => 1, + 'currency_code' => 'USD', + 'resources' => [ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + ], + 'location_id' => 3, + 'node_id' => 7, + 'provisioning_identity' => [ + 'nest_id' => 1, + 'egg_id' => 2, + 'user_external_id' => + "paymenter-user-{$service->user_id}", + 'user_email' => (string) $service->user->email, + ], + 'allocations' => [[ + 'allocation_id' => 7001, + 'ip' => '192.0.2.10', + 'port' => 25565, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ]], + ]; + $fingerprint = (new ReservationConfigurationService) + ->fingerprint($payload); + $reservationId = $this->insertReservation($service, [ + 'status' => 'pending', + 'server_extension_id' => 41, + 'panel_identity' => $panel, + 'configuration_fingerprint' => $fingerprint, + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + 'consumed_at' => null, + ]); + + $blockers = (new LegacyReservationReadinessService)->blockers(); + $blocker = collect($blockers)->firstWhere( + 'reservation_id', + $reservationId + ); + + $this->assertNotNull($blocker); + $this->assertContains( + 'active signed allocation claims', + $blocker['missing'] + ); + + DB::table('ptero_reservation_allocations')->insert([ + 'reservation_id' => $reservationId, + 'panel_identity' => $panel, + 'node_id' => 7, + 'allocation_id' => 7001, + 'ip' => '192.0.2.10', + 'port' => 25565, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + 'created_at' => now(), + 'updated_at' => now(), + ]); + + (new LegacyReservationReadinessService)->assertReady(); + $this->addToAssertionCount(1); + } + + private function service(): Service + { + $user = User::factory()->create(); + $product = Product::factory()->create(); + $plan = Plan::factory()->create([ + 'priceable_id' => $product->id, + 'priceable_type' => Product::class, + ]); + + return Service::factory()->create([ + 'user_id' => $user->id, + 'product_id' => $product->id, + 'plan_id' => $plan->id, + 'quantity' => 1, + 'currency_code' => 'USD', + ]); + } + + /** + * @param array $overrides + */ + private function insertReservation( + Service $service, + array $overrides + ): int { + return DB::table('ptero_resource_reservations')->insertGetId( + array_merge([ + 'token' => bin2hex(random_bytes(32)), + 'purpose' => 'checkout', + 'server_extension_id' => 41, + 'panel_identity' => + hash('sha256', 'https://panel.example.com'), + 'service_id' => $service->id, + 'service_guard_id' => $service->id, + 'user_id' => $service->user_id, + 'product_id' => $service->product_id, + 'plan_id' => $service->plan_id, + 'quantity' => 1, + 'currency_code' => 'USD', + 'node_id' => 7, + 'location_id' => 3, + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + 'reserved_memory' => 0, + 'reserved_cpu' => 0, + 'reserved_disk' => 0, + 'calculated_price' => '10.00', + 'pricing_breakdown' => json_encode( + [], + JSON_THROW_ON_ERROR + ), + 'status' => 'confirmed', + 'expires_at' => now()->subDay(), + 'guaranteed_until' => now()->subDay(), + 'consumed_at' => now()->subDay(), + 'external_server_id' => null, + 'external_user_id' => null, + 'external_server_uuid' => null, + 'external_server_identifier' => null, + 'created_at' => now()->subDay(), + 'updated_at' => now()->subDay(), + ], $overrides) + ); + } +} diff --git a/tests/Feature/ManagedNodeIsolationTest.php b/tests/Feature/ManagedNodeIsolationTest.php new file mode 100644 index 0000000..bc3d1a8 --- /dev/null +++ b/tests/Feature/ManagedNodeIsolationTest.php @@ -0,0 +1,143 @@ +provisioner = new Pterodactyl([ + 'host' => 'https://panel.example.com', + 'api_key' => 'secret', + ]); + DB::table('ptero_node_capacity_policies')->insert([ + 'panel_identity' => hash('sha256', 'https://panel.example.com'), + 'node_uuid' => '00000000-0000-0000-0000-000000000007', + 'node_id' => 7, + 'location_id' => 3, + 'cpu_capacity_percent' => 800, + 'cpu_overcommit_bps' => 10000, + 'enabled' => true, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + + public function test_static_create_rejects_a_managed_node(): void + { + $this->assertStaticCreateRejected( + ['node' => 7, 'location_ids' => [3]], + 'dedicated to reservation-backed dynamic products' + ); + } + + public function test_static_auto_deploy_rejects_any_scope_that_can_reach_a_managed_node(): void + { + $this->assertStaticCreateRejected( + ['node' => null, 'location_ids' => [3, 4]], + 'location with reservation-managed nodes' + ); + $this->assertStaticCreateRejected( + ['node' => null, 'location_ids' => []], + 'spans nodes dedicated to reservation-backed dynamic products' + ); + } + + public function test_static_create_preserves_unmanaged_node_and_location_paths(): void + { + $method = new \ReflectionMethod( + Pterodactyl::class, + 'assertStaticCreateAvoidsManagedNodes' + ); + $method->setAccessible(true); + + $method->invoke( + $this->provisioner, + ['node' => 8, 'location_ids' => [3]] + ); + $method->invoke( + $this->provisioner, + ['node' => null, 'location_ids' => [4]] + ); + + $this->addToAssertionCount(2); + } + + public function test_non_capacity_upgrade_rejects_managed_node_and_preserves_unmanaged_node(): void + { + $method = new \ReflectionMethod( + Pterodactyl::class, + 'assertStaticUpgradeAvoidsManagedNode' + ); + $method->setAccessible(true); + + try { + $method->invoke($this->provisioner, [ + 'attributes' => ['node' => 7], + ]); + $this->fail('Expected managed-node upgrade isolation to fail closed.'); + } catch (\ReflectionException $exception) { + throw $exception; + } catch (\Throwable $exception) { + $actual = $exception instanceof \ReflectionException + ? $exception + : ($exception->getPrevious() ?? $exception); + $this->assertInstanceOf( + PermanentProvisioningException::class, + $actual + ); + $this->assertStringContainsString( + 'capacity-aware upgrade', + $actual->getMessage() + ); + } + + $method->invoke($this->provisioner, [ + 'attributes' => ['node' => 8], + ]); + $this->addToAssertionCount(1); + } + + /** + * @param array $settings + */ + private function assertStaticCreateRejected( + array $settings, + string $message + ): void { + $method = new \ReflectionMethod( + Pterodactyl::class, + 'assertStaticCreateAvoidsManagedNodes' + ); + $method->setAccessible(true); + + try { + $method->invoke($this->provisioner, $settings); + $this->fail('Expected static managed-node isolation to fail closed.'); + } catch (\ReflectionException $exception) { + throw $exception; + } catch (\Throwable $exception) { + $actual = $exception->getPrevious() ?? $exception; + $this->assertInstanceOf( + PermanentProvisioningException::class, + $actual + ); + $this->assertStringContainsString( + $message, + $actual->getMessage() + ); + } + } +} diff --git a/tests/Feature/PricingPreviewParityTest.php b/tests/Feature/PricingPreviewParityTest.php deleted file mode 100644 index ed2d24b..0000000 --- a/tests/Feature/PricingPreviewParityTest.php +++ /dev/null @@ -1,158 +0,0 @@ - User::factory()->create()); - $product = Product::factory()->create(); - $plan = Plan::factory()->create([ - 'priceable_id' => $product->id, - 'priceable_type' => Product::class, - 'name' => 'Monthly', - 'billing_unit' => 'month', - 'billing_period' => 1, - 'type' => 'recurring', - 'dynamic_slider_base_price' => 5.00, - ]); - - Price::factory()->create([ - 'plan_id' => $plan->id, - 'price' => 10.00, - 'setup_fee' => 0.00, - 'currency_code' => 'USD', - ]); - - $memory = $this->attachSlider($product, 'Memory', 'memory', 1024, [ - 'model' => 'linear', - 'rate_per_unit' => 1.50, - ]); - $cpu = $this->attachSlider($product, 'CPU', 'cpu', 100, [ - 'model' => 'linear', - 'rate_per_unit' => 2.00, - ]); - $disk = $this->attachSlider($product, 'Disk', 'disk', 1024, [ - 'model' => 'linear', - 'rate_per_unit' => 0.25, - ]); - - $payload = [ - 'product_id' => $product->id, - 'plan_id' => $plan->id, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 20480, - ]; - - $response = $this->actingAs($user) - ->withSession($this->loginUser($user)) - ->postJson('/api/dynamic-pterodactyl/pricing/calculate', $payload); - - $response->assertOk()->assertJson(['success' => true]); - - $expectedDelta = $memory->calculateDynamicPriceDelta(4096, 1, 'month') - + $cpu->calculateDynamicPriceDelta(200, 1, 'month') - + $disk->calculateDynamicPriceDelta(20480, 1, 'month'); - - $this->assertEquals(round($expectedDelta + 5.00, 2), $response->json('data.total')); - $response->assertJsonCount(3, 'data.breakdown'); - $response->assertJsonPath('data.model', 'linear'); - } - - private function attachSlider(Product $product, string $name, string $resourceType, int $displayDivisor, array $pricing): ConfigOption - { - $option = ConfigOption::create([ - 'name' => $name, - 'env_variable' => strtoupper($resourceType), - 'type' => 'dynamic_slider', - 'sort' => 0, - 'hidden' => false, - 'upgradable' => true, - 'metadata' => [ - 'resource_type' => $resourceType, - 'min' => $displayDivisor, - 'max' => $displayDivisor * 64, - 'step' => $displayDivisor, - 'default' => $displayDivisor, - 'unit' => $resourceType === 'cpu' ? '%' : 'MB', - 'display_unit' => $resourceType === 'cpu' ? 'cores' : 'GB', - 'display_divisor' => $displayDivisor, - 'pricing' => $pricing, - ], - ]); - - DB::table('config_option_products')->insert([ - 'product_id' => $product->id, - 'config_option_id' => $option->id, - ]); - - return $option; - } - public function test_pricing_calculate_with_foreign_plan_id_returns_client_error(): void - { - /** @var User $user */ - $user = User::withoutEvents(fn () => User::factory()->create()); - - $product = Product::factory()->create(); - $otherProduct = Product::factory()->create(); - - $this->attachSlider($product, 'Memory', 'memory', 1024, [ - 'model' => 'linear', - 'rate_per_unit' => 1.50, - ]); - - $foreignPlan = Plan::factory()->create([ - 'priceable_id' => $otherProduct->id, - 'priceable_type' => Product::class, - 'name' => 'Other Plan', - 'billing_unit' => 'month', - 'billing_period' => 1, - 'type' => 'recurring', - 'dynamic_slider_base_price' => 5.00, - ]); - - Price::factory()->create([ - 'plan_id' => $foreignPlan->id, - 'price' => 10.00, - 'setup_fee' => 0.00, - 'currency_code' => 'USD', - ]); - - $payload = [ - 'product_id' => $product->id, - 'plan_id' => $foreignPlan->id, - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 20480, - ]; - - $response = $this->actingAs($user) - ->withSession($this->loginUser($user)) - ->postJson('/api/dynamic-pterodactyl/pricing/calculate', $payload); - - $response->assertStatus(422); - $response->assertJson(['success' => false]); - } - -} diff --git a/tests/Feature/ResourceQuoteApiTest.php b/tests/Feature/ResourceQuoteApiTest.php new file mode 100644 index 0000000..6ecca23 --- /dev/null +++ b/tests/Feature/ResourceQuoteApiTest.php @@ -0,0 +1,315 @@ +quoteableProduct(); + $quotes = Mockery::mock(ResourceQuoteService::class); + $quotes->shouldReceive('quote') + ->once() + ->with( + Mockery::on(fn (Product $resolved): bool => $resolved->is($product)), + ['10' => 32768], + null + ) + ->andReturn([ + 'available' => true, + 'adjusted' => true, + 'selection' => [ + 'memory' => 23552, + 'cpu' => 200, + 'disk' => 51200, + ], + 'bounds' => [ + 'memory' => [ + 'config_option_id' => 10, + 'min' => 1024, + 'max' => 23552, + 'configured_max' => 32768, + 'step' => 1024, + ], + ], + ]); + $this->app->instance(ResourceQuoteService::class, $quotes); + + $response = $this->postJson( + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", + ['config_options' => ['10' => 32768]] + ); + + $response->assertOk()->assertExactJson([ + 'data' => [ + 'available' => true, + 'adjusted' => true, + 'selection' => [ + 'memory' => 23552, + 'cpu' => 200, + 'disk' => 51200, + ], + 'bounds' => [ + 'memory' => [ + 'config_option_id' => 10, + 'min' => 1024, + 'max' => 23552, + 'configured_max' => 32768, + 'step' => 1024, + ], + ], + ], + ]); + $this->assertStringNotContainsString('node', $response->getContent()); + } + + public function test_invalid_request_has_safe_top_level_422_message(): void + { + $product = $this->quoteableProduct(); + + $this->postJson( + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", + [] + )->assertStatus(422)->assertJson([ + 'message' => 'The resource quote request is invalid.', + ]); + } + + public function test_stock_conflict_has_safe_top_level_409_message(): void + { + $product = $this->quoteableProduct(); + $quotes = Mockery::mock(ResourceQuoteService::class); + $quotes->shouldReceive('quote') + ->once() + ->andThrow(new StockUnavailableException('No server currently has enough stock.')); + $this->app->instance(ResourceQuoteService::class, $quotes); + + $this->postJson( + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", + ['config_options' => []] + )->assertStatus(409)->assertExactJson([ + 'message' => 'No server currently has enough stock.', + ]); + } + + public function test_upstream_failure_does_not_leak_panel_details(): void + { + $product = $this->quoteableProduct(); + $quotes = Mockery::mock(ResourceQuoteService::class); + $quotes->shouldReceive('quote') + ->once() + ->andThrow(new \RuntimeException('panel-internal.example:8443 refused')); + $this->app->instance(ResourceQuoteService::class, $quotes); + + $response = $this->postJson( + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", + ['config_options' => []] + ); + + $response->assertStatus(503)->assertExactJson([ + 'message' => 'Dynamic stock is temporarily unavailable.', + ]); + $this->assertStringNotContainsString('panel-internal', $response->getContent()); + } + + public function test_owned_cart_item_quote_excludes_its_current_hold(): void + { + $product = $this->quoteableProduct(); + $cart = Cart::create(['currency_code' => 'USD']); + $cartItemId = DB::table('cart_items')->insertGetId([ + 'cart_id' => $cart->id, + 'product_id' => $product->id, + 'plan_id' => $product->plans()->value('id'), + 'config_options' => json_encode([]), + 'checkout_config' => json_encode([]), + 'quantity' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); + DB::table('ptero_resource_reservations')->insert([ + 'token' => 'owned-cart-hold', + 'cart_item_id' => $cartItemId, + 'cart_item_guard_id' => $cartItemId, + 'node_id' => 5, + 'location_id' => 1, + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 51200, + 'calculated_price' => 0, + 'pricing_breakdown' => json_encode([]), + 'status' => 'pending', + 'expires_at' => now()->addMinutes(15), + 'created_at' => now(), + 'updated_at' => now(), + ]); + + $quotes = Mockery::mock(ResourceQuoteService::class); + $quotes->shouldReceive('quote') + ->once() + ->with( + Mockery::on(fn (Product $resolved): bool => $resolved->is($product)), + [], + 'owned-cart-hold' + ) + ->andReturn([ + 'available' => true, + 'adjusted' => false, + 'selection' => ['memory' => 4096, 'cpu' => 200, 'disk' => 51200], + 'bounds' => [], + ]); + $this->app->instance(ResourceQuoteService::class, $quotes); + + $this->withCookie('cart', $cart->ulid) + ->postJson( + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", + ['config_options' => [], 'cart_item_id' => $cartItemId] + ) + ->assertOk(); + } + + public function test_cart_item_from_another_cart_cannot_be_used_for_exclusion(): void + { + $product = $this->quoteableProduct(); + $ownedCart = Cart::create(['currency_code' => 'USD']); + $otherCart = Cart::create(['currency_code' => 'USD']); + $otherItemId = DB::table('cart_items')->insertGetId([ + 'cart_id' => $otherCart->id, + 'product_id' => $product->id, + 'plan_id' => $product->plans()->value('id'), + 'config_options' => json_encode([]), + 'checkout_config' => json_encode([]), + 'quantity' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); + + $this->withCookie('cart', $ownedCart->ulid) + ->postJson( + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", + ['config_options' => [], 'cart_item_id' => $otherItemId] + ) + ->assertStatus(422) + ->assertJson([ + 'message' => 'The cart item is not available for this resource quote.', + ]); + } + + public function test_hidden_product_is_rejected_before_quote_service(): void + { + $product = $this->quoteableProduct(); + $product->update(['hidden' => true]); + + $this->postJson( + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", + ['config_options' => []] + )->assertStatus(404); + } + + public function test_out_of_stock_product_is_rejected_before_quote_service(): void + { + $product = $this->quoteableProduct(); + $product->update(['stock' => 0]); + + $this->postJson( + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", + ['config_options' => []] + )->assertStatus(404); + } + + public function test_unpriced_product_is_rejected_before_quote_service(): void + { + $product = $this->quoteableProduct(); + $product->plans()->delete(); + + $this->postJson( + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", + ['config_options' => []] + )->assertStatus(404); + } + + public function test_non_pterodactyl_product_is_rejected_before_panel_read(): void + { + $product = $this->quoteableProduct(); + $product->server->update(['extension' => 'OtherServer']); + + $this->postJson( + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", + ['config_options' => []] + )->assertStatus(404); + } + + public function test_non_dynamic_product_is_rejected_before_panel_read(): void + { + $product = $this->quoteableProduct(); + DB::table('config_option_products') + ->where('product_id', $product->id) + ->delete(); + + $this->postJson( + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", + ['config_options' => []] + )->assertStatus(404); + } + + private function quoteableProduct(): Product + { + $server = Server::create([ + 'name' => 'Pterodactyl', + 'extension' => 'Pterodactyl', + 'type' => 'server', + 'enabled' => true, + ]); + $product = Product::factory()->create([ + 'server_id' => $server->id, + 'hidden' => false, + 'stock' => null, + ]); + $product->plans()->create([ + 'name' => 'Free', + 'type' => 'free', + 'billing_period' => 1, + 'billing_unit' => 'month', + ]); + $slider = ConfigOption::create([ + 'name' => 'Memory', + 'env_variable' => 'memory', + 'type' => 'dynamic_slider', + 'sort' => 0, + 'hidden' => false, + 'upgradable' => false, + 'metadata' => [ + 'resource_type' => 'memory', + 'min' => 1024, + 'max' => 32768, + 'step' => 1024, + 'default' => 4096, + ], + ]); + DB::table('config_option_products')->insert([ + 'product_id' => $product->id, + 'config_option_id' => $slider->id, + ]); + + return $product; + } +} diff --git a/tests/Feature/SetupWizardValidationTest.php b/tests/Feature/SetupWizardValidationTest.php index 0834247..ba9bec3 100644 --- a/tests/Feature/SetupWizardValidationTest.php +++ b/tests/Feature/SetupWizardValidationTest.php @@ -3,6 +3,7 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Feature; use App\Models\Product; +use App\Models\Server; use App\Models\User; use Filament\Notifications\Notification; use Illuminate\Foundation\Testing\DatabaseTransactions; @@ -11,6 +12,7 @@ use Mockery; use Paymenter\Extensions\Others\DynamicPterodactyl\Admin\Pages\SetupWizard; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ConfigOptionSetupService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\PterodactylInventoryService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceCalculationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; @@ -31,6 +33,12 @@ protected function setUp(): void $resourceService->shouldReceive('getLocations')->zeroOrMoreTimes()->andReturn($locations); $this->app->instance(ResourceCalculationService::class, $resourceService); + $inventory = Mockery::mock(PterodactylInventoryService::class); + $inventory->shouldReceive('locations')->zeroOrMoreTimes()->andReturn($locations); + $inventory->shouldReceive('panelIdentity') + ->zeroOrMoreTimes() + ->andReturn(hash('sha256', 'https://panel.example')); + $this->app->instance(PterodactylInventoryService::class, $inventory); $this->app['view']->addNamespace('dynamic-pterodactyl', __DIR__ . '/../../resources/views'); } @@ -45,7 +53,7 @@ public function test_wizard_rejects_invalid_pricing_with_form_error(): void { $this->actingAsAdmin(); - $product = Product::factory()->create(); + $product = $this->eligibleProduct(); Livewire::test(SetupWizard::class) ->fillForm([ @@ -68,7 +76,7 @@ public function test_wizard_creates_three_sliders_and_location_on_valid_submissi { $this->actingAsAdmin(); - $product = Product::factory()->create(); + $product = $this->eligibleProduct(); // Filament harness fallback — see dp-13 plan commit 4 notes. app(ConfigOptionSetupService::class)->createDynamicSliderOptions( @@ -96,7 +104,7 @@ public function test_wizard_rollback_on_validator_failure_mid_batch(): void { $this->actingAsAdmin(); - $product = Product::factory()->create(); + $product = $this->eligibleProduct(); // Filament harness fallback — see dp-13 plan commit 4 notes. try { @@ -113,7 +121,8 @@ public function test_wizard_rollback_on_validator_failure_mid_batch(): void ['up_to' => null, 'rate' => 2.00], ], 'disk_tiers' => [], - ] + ], + [['id' => 1, 'short' => 'nyc', 'long' => 'New York']] ); $this->fail('Expected the setup service to reject the invalid disk tiers.'); @@ -148,7 +157,7 @@ private function baseWizardData(int $productId): array 'memory_rate' => 0.50, 'cpu_rate' => 2.00, 'disk_rate' => 0.02, - 'locations' => [], + 'locations' => [1], ]; } @@ -169,4 +178,25 @@ private function actingAsAdmin(): User return $admin; } + + private function eligibleProduct(): Product + { + $server = Server::create([ + 'name' => 'Pterodactyl', + 'extension' => 'Pterodactyl', + 'type' => 'server', + 'enabled' => true, + ]); + $server->settings()->create([ + 'key' => 'host', + 'value' => 'https://panel.example', + 'type' => 'string', + 'encrypted' => false, + ]); + + return Product::factory()->create([ + 'server_id' => $server->id, + 'hidden' => false, + ]); + } } diff --git a/tests/LaravelTestCase.php b/tests/LaravelTestCase.php index d87e535..e9c5562 100644 --- a/tests/LaravelTestCase.php +++ b/tests/LaravelTestCase.php @@ -211,8 +211,14 @@ protected function createNodeData( 'node_id' => $nodeId, 'name' => $name, 'maintenance_mode' => $maintenance, + 'eligible' => ! $maintenance, 'total' => $total, 'available' => $available, + 'available_allocations' => [[ + 'id' => ($nodeId * 1000) + 1, + 'ip' => '192.0.2.'.$nodeId, + 'port' => 25565, + ]], ]; } diff --git a/tests/TestCase.php b/tests/TestCase.php index 69e0716..4c08bde 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -44,8 +44,14 @@ protected function createNodeData( 'node_id' => $nodeId, 'name' => $name, 'maintenance_mode' => $maintenance, + 'eligible' => ! $maintenance, 'total' => $total, 'available' => $available, + 'available_allocations' => [[ + 'id' => ($nodeId * 1000) + 1, + 'ip' => '192.0.2.'.$nodeId, + 'port' => 25565, + ]], ]; } diff --git a/tests/Unit/AlertServiceTest.php b/tests/Unit/AlertServiceTest.php index ec73f3b..11a79c5 100644 --- a/tests/Unit/AlertServiceTest.php +++ b/tests/Unit/AlertServiceTest.php @@ -14,6 +14,7 @@ use Paymenter\Extensions\Others\DynamicPterodactyl\Events\AlertDeliveryFailed; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\AlertConfig; use Paymenter\Extensions\Others\DynamicPterodactyl\Notifications\CapacityAlertNotification; +use Paymenter\Extensions\Others\DynamicPterodactyl\Notifications\ProvisioningFailedNotification; use Paymenter\Extensions\Others\DynamicPterodactyl\Notifications\ReservationShortfallNotification; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AuditLogService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AlertService; @@ -84,6 +85,61 @@ private function invokeSendNotifications(AlertService $service, object $config, return $method->invoke($service, $config, $availability, $alerts); } + public function test_capacity_thresholds_include_holds_and_authoritative_cpu(): void + { + $method = new \ReflectionMethod( + AlertService::class, + 'checkThresholds' + ); + $method->setAccessible(true); + $alerts = $method->invoke( + $this->makeService(), + [ + 'total_capacity' => [ + 'memory' => 100, + 'cpu' => 100, + 'disk' => 100, + ], + // Only ten is provisioned; the other 85 is held capacity. + 'total_allocated' => [ + 'memory' => 10, + 'cpu' => 10, + 'disk' => 10, + ], + 'total_available' => [ + 'memory' => 5, + 'cpu' => 15, + 'disk' => 90, + ], + ], + (object) [ + 'memory_warning_threshold' => 80, + 'memory_critical_threshold' => 90, + 'cpu_warning_threshold' => 80, + 'cpu_critical_threshold' => 90, + 'disk_warning_threshold' => 80, + 'disk_critical_threshold' => 90, + ] + ); + + $this->assertSame([ + [ + 'type' => 'critical', + 'resource' => 'memory', + 'utilization' => 95.0, + 'usage_percent' => 95.0, + 'threshold' => 90, + ], + [ + 'type' => 'warning', + 'resource' => 'cpu', + 'utilization' => 85.0, + 'usage_percent' => 85.0, + 'threshold' => 80, + ], + ], $alerts); + } + public function test_notify_shortfall_emails_all_admins(): void { $recipientA = new class @@ -481,6 +537,52 @@ private function runCheck(AlertService $service, AlertConfig $alertConfig): void $method->invoke($service, $alertConfig); } + public function test_terminal_upgrade_failure_notifies_and_audits_full_identity(): void + { + Notification::fake(); + $admin = User::factory()->create(['role_id' => 1]); + $service = $this->makeService( + Mockery::mock(ResourceCalculationService::class) + ); + $snapshot = [ + 'operation' => 'upgrade', + 'upgrade_id' => 41, + 'service_id' => 42, + 'invoice_id' => 43, + 'reservation_id' => 44, + 'node_id' => 45, + 'attempts' => 5, + 'error' => 'Panel rejected the build.', + ]; + + $service->notifyUpgradeFailure($snapshot); + + Notification::assertSentTo( + $admin, + ProvisioningFailedNotification::class, + fn (ProvisioningFailedNotification $notification): bool => + $notification->snapshot === $snapshot + ); + $this->assertDatabaseHas('ptero_audit_logs', [ + 'action' => 'upgrade_failure_alerted', + 'entity_type' => 'resource_reservation', + 'entity_id' => 44, + ]); + $audit = DB::table('ptero_audit_logs') + ->where('action', 'upgrade_failure_alerted') + ->where('entity_id', 44) + ->latest('id') + ->first(); + $this->assertSame([ + 'upgrade_id' => 41, + 'service_id' => 42, + 'invoice_id' => 43, + 'reservation_id' => 44, + 'attempts' => 5, + 'error' => 'Panel rejected the build.', + ], json_decode($audit->new_values, true)); + } + public function test_capacity_alert_writes_audit_row_on_successful_send(): void { Notification::fake(); diff --git a/tests/Unit/AllocationSelectionServiceTest.php b/tests/Unit/AllocationSelectionServiceTest.php new file mode 100644 index 0000000..aa8fd03 --- /dev/null +++ b/tests/Unit/AllocationSelectionServiceTest.php @@ -0,0 +1,141 @@ +select([ + [ + 'id' => 1, + 'ip' => '192.0.2.10', + 'port' => 25565, + 'ip_in_use' => true, + ], + [ + 'id' => 2, + 'ip' => '192.0.2.10', + 'port' => 25566, + 'ip_in_use' => false, + ], + [ + 'id' => 3, + 'ip' => '192.0.2.11', + 'port' => 25565, + 'ip_in_use' => false, + ], + [ + 'id' => 4, + 'ip' => '192.0.2.11', + 'port' => 25566, + 'ip_in_use' => false, + ], + ], 2, dedicatedIp: true); + + $this->assertSame([3, 4], array_column($selected, 'id')); + } + + public function test_equivalent_ipv6_spellings_share_one_dedicated_ip_group(): void + { + $selected = (new AllocationSelectionService())->select([ + [ + 'id' => 10, + 'ip' => '2001:db8::1', + 'port' => 25565, + 'ip_in_use' => false, + ], + [ + 'id' => 11, + 'ip' => '2001:0db8:0:0:0:0:0:1', + 'port' => 25566, + 'ip_in_use' => false, + ], + ], 2, dedicatedIp: true); + + $this->assertSame([10, 11], array_column($selected, 'id')); + } + + public function test_port_range_constrains_primary_but_not_preclaimed_extras(): void + { + $selected = (new AllocationSelectionService())->select([ + [ + 'id' => 20, + 'ip' => '192.0.2.20', + 'port' => 20000, + 'ip_in_use' => false, + ], + [ + 'id' => 21, + 'ip' => '192.0.2.20', + 'port' => 25565, + 'ip_in_use' => false, + ], + ], 2, allowedPortRanges: [ + ['from' => 25560, 'to' => 25570], + ]); + + $this->assertSame([21, 20], array_column($selected, 'id')); + } + + public function test_dedicated_fixed_ports_must_exist_on_the_same_ip(): void + { + $selected = (new AllocationSelectionService())->select([ + [ + 'id' => 30, + 'ip' => '192.0.2.30', + 'port' => 25565, + 'ip_in_use' => false, + ], + [ + 'id' => 31, + 'ip' => '192.0.2.31', + 'port' => 25566, + 'ip_in_use' => false, + ], + ], 2, [25565, 25566], dedicatedIp: true); + + $this->assertNull($selected); + } + + public function test_repeated_port_across_ips_uses_lowest_allocation_id(): void + { + $selected = (new AllocationSelectionService())->select([ + [ + 'id' => 101, + 'ip' => '192.0.2.11', + 'port' => 25570, + ], + [ + 'id' => 100, + 'ip' => '192.0.2.10', + 'port' => 25570, + ], + ], 1, [25570]); + + $this->assertSame([100], array_column($selected, 'id')); + } + + public function test_dedicated_repeated_port_uses_lowest_eligible_ip_group(): void + { + $selected = (new AllocationSelectionService())->select([ + [ + 'id' => 202, + 'ip' => '192.0.2.22', + 'port' => 25570, + 'ip_in_use' => false, + ], + [ + 'id' => 201, + 'ip' => '192.0.2.21', + 'port' => 25570, + 'ip_in_use' => false, + ], + ], 1, [25570], dedicatedIp: true); + + $this->assertSame([201], array_column($selected, 'id')); + } +} diff --git a/tests/Unit/ConfigOptionSetupServiceTest.php b/tests/Unit/ConfigOptionSetupServiceTest.php index a7f165e..16da5a8 100644 --- a/tests/Unit/ConfigOptionSetupServiceTest.php +++ b/tests/Unit/ConfigOptionSetupServiceTest.php @@ -3,18 +3,40 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; use App\Models\ConfigOption; +use App\Models\Invoice; use App\Models\Product; +use App\Models\Server; +use App\Models\Service; +use App\Models\User; +use App\Services\Service\CapacityServiceCreationCoordinator; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Str; use Mockery; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AuditLogService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ConfigOptionSetupService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\PterodactylInventoryService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; class ConfigOptionSetupServiceTest extends LaravelTestCase { use DatabaseTransactions; + protected function setUp(): void + { + parent::setUp(); + + $inventory = Mockery::mock(PterodactylInventoryService::class); + $inventory->shouldReceive('locations')->zeroOrMoreTimes()->andReturn([ + ['id' => 1, 'short' => 'nyc', 'long' => 'New York'], + ['id' => 2, 'short' => 'lon', 'long' => 'London'], + ]); + $inventory->shouldReceive('panelIdentity') + ->zeroOrMoreTimes() + ->andReturn(hash('sha256', 'https://panel.example')); + app()->instance(PterodactylInventoryService::class, $inventory); + } + protected function tearDown(): void { Mockery::close(); @@ -24,7 +46,7 @@ protected function tearDown(): void public function test_createDynamicSliderOptions_rolls_back_on_mid_batch_failure(): void { - $product = Product::factory()->create(); + $product = $this->eligibleProduct(); try { app(ConfigOptionSetupService::class)->createDynamicSliderOptions( @@ -39,7 +61,8 @@ public function test_createDynamicSliderOptions_rolls_back_on_mid_batch_failure( ['up_to' => null, 'rate' => 2.00], ], 'disk_tiers' => [], - ] + ], + [['id' => 1, 'short' => 'nyc', 'long' => 'New York']] ); $this->fail('Expected setup to reject the invalid disk pricing tiers.'); @@ -52,7 +75,7 @@ public function test_createDynamicSliderOptions_rolls_back_on_mid_batch_failure( public function test_createDynamicSliderOptions_happy_path_creates_all_four(): void { - $product = Product::factory()->create(); + $product = $this->eligibleProduct(); $created = app(ConfigOptionSetupService::class)->createDynamicSliderOptions( $product->id, @@ -77,7 +100,7 @@ public function test_createDynamicSliderOptions_happy_path_creates_all_four(): v public function test_setup_run_audit_still_fires_on_successful_transaction(): void { - $product = Product::factory()->create(); + $product = $this->eligibleProduct(); $audit = Mockery::mock(AuditLogService::class); $audit->shouldReceive('log') @@ -105,6 +128,214 @@ public function test_setup_run_audit_still_fires_on_successful_transaction(): vo $this->assertSame(4, $this->countParentOptionsForProduct($product->id)); } + public function test_fractional_display_values_scale_exactly_without_truncation(): void + { + $product = $this->eligibleProduct(); + + $created = app(ConfigOptionSetupService::class) + ->createDynamicSliderOptions( + $product->id, + [ + 'pricing_model' => 'linear', + 'memory_min' => '0.5', + 'memory_max' => '2', + 'memory_step' => '0.5', + 'memory_default' => '1', + 'memory_rate' => 1, + 'cpu_rate' => 1, + 'disk_rate' => 1, + ], + [['id' => 1, 'short' => 'nyc', 'long' => 'New York']] + ); + + $this->assertSame(512, $created['memory']->metadata['min']); + $this->assertSame(512, $created['memory']->metadata['step']); + $this->assertSame(1024, $created['memory']->metadata['default']); + $this->assertSame(2048, $created['memory']->metadata['max']); + } + + public function test_fractional_display_value_that_cannot_scale_exactly_is_rejected(): void + { + $product = $this->eligibleProduct(); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('represented exactly'); + app(ConfigOptionSetupService::class)->createDynamicSliderOptions( + $product->id, + [ + 'pricing_model' => 'linear', + 'memory_min' => '0.0001', + 'memory_rate' => 1, + 'cpu_rate' => 1, + 'disk_rate' => 1, + ], + [['id' => 1, 'short' => 'nyc', 'long' => 'New York']] + ); + } + + public function test_scaled_value_overflow_is_rejected(): void + { + $product = $this->eligibleProduct(); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('outside the supported range'); + app(ConfigOptionSetupService::class)->createDynamicSliderOptions( + $product->id, + [ + 'pricing_model' => 'linear', + 'memory_max' => (string) PHP_INT_MAX, + 'memory_rate' => 1, + 'cpu_rate' => 1, + 'disk_rate' => 1, + ], + [['id' => 1, 'short' => 'nyc', 'long' => 'New York']] + ); + } + + public function test_unmanaged_resource_name_collision_fails_closed(): void + { + $product = $this->eligibleProduct(); + $option = ConfigOption::create([ + 'name' => 'Memory', + 'env_variable' => 'memory', + 'type' => 'number', + 'hidden' => false, + ]); + $option->products()->attach($product->id); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('unmanaged memory'); + app(ConfigOptionSetupService::class)->createDynamicSliderOptions( + $product->id, + [ + 'pricing_model' => 'linear', + 'memory_rate' => 1, + 'cpu_rate' => 1, + 'disk_rate' => 1, + ], + [['id' => 1, 'short' => 'nyc', 'long' => 'New York']] + ); + } + + public function test_setup_rejects_a_product_on_a_different_panel(): void + { + $product = $this->eligibleProduct([ + 'provisioner_host' => 'https://other-panel.example', + ]); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('same panel'); + app(ConfigOptionSetupService::class)->createDynamicSliderOptions( + $product->id, + [ + 'pricing_model' => 'linear', + 'memory_rate' => 1, + 'cpu_rate' => 1, + 'disk_rate' => 1, + ], + [['id' => 1, 'short' => 'nyc', 'long' => 'New York']] + ); + } + + public function test_wizard_rerun_preserves_bound_invoice_guarantee_snapshot(): void + { + $product = $this->eligibleProduct(); + $service = app(ConfigOptionSetupService::class); + $service->createDynamicSliderOptions( + $product->id, + [ + 'pricing_model' => 'linear', + 'memory_max' => 32, + 'memory_rate' => 1, + 'cpu_rate' => 1, + 'disk_rate' => 1, + ], + [['id' => 1, 'short' => 'nyc', 'long' => 'New York']] + ); + + $user = User::factory()->create(); + $boundService = CapacityServiceCreationCoordinator::run( + fn () => Service::factory()->create([ + 'user_id' => $user->id, + 'product_id' => $product->id, + 'quantity' => 1, + 'price' => 10, + 'currency_code' => 'USD', + 'status' => Service::STATUS_PENDING, + ]) + ); + $invoice = Invoice::factory()->create([ + 'user_id' => $user->id, + 'currency_code' => 'USD', + 'status' => Invoice::STATUS_PENDING, + 'due_at' => now()->addDays(4), + ]); + $payload = [ + 'product_id' => $product->id, + 'memory' => 32768, + 'cpu' => 200, + 'disk' => 20480, + ]; + $reservationId = DB::table('ptero_resource_reservations')->insertGetId([ + 'token' => Str::random(64), + 'purpose' => 'checkout', + 'idempotency_key' => hash('sha256', Str::random()), + 'server_extension_id' => $product->server_id, + 'panel_identity' => str_repeat('a', 64), + 'service_id' => $boundService->id, + 'service_guard_id' => $boundService->id, + 'invoice_id' => $invoice->id, + 'user_id' => $user->id, + 'product_id' => $product->id, + 'quantity' => 1, + 'currency_code' => 'USD', + 'configuration_fingerprint' => hash( + 'sha256', + json_encode($payload, JSON_THROW_ON_ERROR) + ), + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + 'pricing_version' => str_repeat('b', 64), + 'formula_version' => 'test-v1', + 'node_id' => 1, + 'location_id' => 1, + 'memory' => 32768, + 'cpu' => 200, + 'disk' => 20480, + 'calculated_price' => 10, + 'pricing_breakdown' => json_encode([], JSON_THROW_ON_ERROR), + 'status' => 'pending', + 'expires_at' => now()->addDays(4), + 'guaranteed_until' => now()->addDays(4), + 'created_at' => now()->subDays(3), + 'updated_at' => now(), + ]); + + $service->createDynamicSliderOptions( + $product->id, + [ + 'pricing_model' => 'linear', + 'memory_max' => 64, + 'memory_rate' => 2, + 'cpu_rate' => 1, + 'disk_rate' => 1, + ], + [['id' => 1, 'short' => 'nyc', 'long' => 'New York']] + ); + + $reservation = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->first(); + $this->assertSame('pending', $reservation->status); + $this->assertSame( + $payload, + json_decode($reservation->configuration_payload, true) + ); + $this->assertSame(Invoice::STATUS_PENDING, $invoice->fresh()->status); + } + private function countOptionsForProduct(int $productId): int { return DB::table('config_options') @@ -113,6 +344,32 @@ private function countOptionsForProduct(int $productId): int ->count(); } + private function eligibleProduct(array $attributes = []): Product + { + $host = (string) ( + $attributes['provisioner_host'] + ?? 'https://panel.example' + ); + unset($attributes['provisioner_host']); + $server = Server::create([ + 'name' => 'Pterodactyl', + 'extension' => 'Pterodactyl', + 'type' => 'server', + 'enabled' => true, + ]); + $server->settings()->create([ + 'key' => 'host', + 'value' => $host, + 'type' => 'string', + 'encrypted' => false, + ]); + + return Product::factory()->create(array_merge([ + 'server_id' => $server->id, + 'hidden' => false, + ], $attributes)); + } + private function countParentOptionsForProduct(int $productId): int { return DB::table('config_options') diff --git a/tests/Unit/NodeCapacityPolicyTest.php b/tests/Unit/NodeCapacityPolicyTest.php new file mode 100644 index 0000000..cd0aaf5 --- /dev/null +++ b/tests/Unit/NodeCapacityPolicyTest.php @@ -0,0 +1,32 @@ + 800, + 'cpu_overcommit_bps' => 15000, + 'enabled' => true, + ]); + + $this->assertSame(1200, $policy->effectiveCpuCapacity()); + } + + public function test_policy_bounds_prevent_overflowing_capacity_math(): void + { + $policy = new NodeCapacityPolicy([ + 'cpu_capacity_percent' => NodeCapacityPolicy::MAX_CPU_CAPACITY_PERCENT + 1, + 'cpu_overcommit_bps' => 10000, + 'enabled' => true, + ]); + + $this->expectException(\InvalidArgumentException::class); + $policy->effectiveCpuCapacity(); + } +} diff --git a/tests/Unit/NodeSelectionServiceTest.php b/tests/Unit/NodeSelectionServiceTest.php index 2963491..b336954 100644 --- a/tests/Unit/NodeSelectionServiceTest.php +++ b/tests/Unit/NodeSelectionServiceTest.php @@ -3,6 +3,7 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; use Mockery; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AllocationSelectionService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\NodeSelectionService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceCalculationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; @@ -17,7 +18,10 @@ protected function setUp(): void parent::setUp(); $this->mockResourceService = Mockery::mock(ResourceCalculationService::class); - $this->service = new NodeSelectionService($this->mockResourceService); + $this->service = new NodeSelectionService( + $this->mockResourceService, + new AllocationSelectionService() + ); } protected function tearDown(): void @@ -153,10 +157,7 @@ public function test_skips_nodes_with_insufficient_memory(): void $this->assertEquals(2, $result['node_id']); } - /** - * CPU limits do not affect node selection without authoritative inventory. - */ - public function test_cpu_is_not_treated_as_hard_capacity(): void + public function test_skips_node_with_insufficient_authoritative_cpu(): void { $this->mockResourceService->shouldReceive('getLocationAvailability') ->with(1, null) @@ -191,7 +192,7 @@ public function test_cpu_is_not_treated_as_hard_capacity(): void ]); $this->assertNotNull($result); - $this->assertEquals(1, $result['node_id']); + $this->assertEquals(2, $result['node_id']); } /** @@ -381,4 +382,135 @@ public function test_empty_nodes_returns_null(): void $this->assertNull($result); } + + public function test_requires_requested_number_of_free_allocations(): void + { + $this->mockResourceService->shouldReceive('getLocationAvailability') + ->with(1, null) + ->andReturn([ + 'nodes' => [ + $this->createNodeData(1, 'Node 1', [ + 'memory' => 16384, + 'cpu' => 800, + 'disk' => 102400, + ], [ + 'memory' => 8192, + 'cpu' => 400, + 'disk' => 51200, + ]), + ], + 'max_available' => [], + ]); + + $result = $this->service->selectBestNodeWithAllocations( + 1, + ['memory' => 4096, 'cpu' => 100, 'disk' => 20480], + allocationCount: 2 + ); + + $this->assertNull($result); + } + + public function test_explicit_port_requirement_is_part_of_node_eligibility(): void + { + $first = $this->createNodeData(1, 'Wrong Port', [ + 'memory' => 16384, + 'cpu' => 800, + 'disk' => 102400, + ], [ + 'memory' => 12288, + 'cpu' => 600, + 'disk' => 76800, + ]); + $second = $this->createNodeData(2, 'Requested Port', [ + 'memory' => 16384, + 'cpu' => 800, + 'disk' => 102400, + ], [ + 'memory' => 8192, + 'cpu' => 400, + 'disk' => 51200, + ]); + $second['available_allocations'][0]['port'] = 25570; + + $this->mockResourceService->shouldReceive('getLocationAvailability') + ->with(1, null) + ->andReturn([ + 'nodes' => [$first, $second], + 'max_available' => [], + ]); + + $result = $this->service->selectBestNodeWithAllocations( + 1, + ['memory' => 4096, 'cpu' => 100, 'disk' => 20480], + 1, + null, + [25570] + ); + + $this->assertSame(2, $result['node_id']); + } + + public function test_required_port_is_selected_even_when_later_in_inventory(): void + { + $node = $this->createNodeData(1, 'Node 1', [ + 'memory' => 16384, + 'cpu' => 800, + 'disk' => 102400, + ], [ + 'memory' => 8192, + 'cpu' => 400, + 'disk' => 51200, + ]); + $node['available_allocations'] = [ + ['id' => 100, 'ip' => '192.0.2.1', 'port' => 25565], + ['id' => 101, 'ip' => '192.0.2.1', 'port' => 25570], + ]; + $this->mockResourceService->shouldReceive('getLocationAvailability') + ->with(1, null) + ->andReturn(['nodes' => [$node], 'max_available' => []]); + + $result = $this->service->selectBestNodeWithAllocations( + 1, + ['memory' => 4096, 'cpu' => 100, 'disk' => 20480], + 1, + null, + [25570] + ); + + $this->assertSame([101], array_column($result['selected_allocations'], 'id')); + } + + public function test_duplicate_port_on_multiple_ips_selects_lowest_allocation_id(): void + { + $node = $this->createNodeData(1, 'Node 1', [ + 'memory' => 16384, + 'cpu' => 800, + 'disk' => 102400, + ], [ + 'memory' => 8192, + 'cpu' => 400, + 'disk' => 51200, + ]); + $node['available_allocations'] = [ + ['id' => 100, 'ip' => '192.0.2.1', 'port' => 25570], + ['id' => 101, 'ip' => '192.0.2.2', 'port' => 25570], + ]; + $this->mockResourceService->shouldReceive('getLocationAvailability') + ->with(1, null) + ->andReturn(['nodes' => [$node], 'max_available' => []]); + + $result = $this->service->selectBestNodeWithAllocations( + 1, + ['memory' => 4096, 'cpu' => 100, 'disk' => 20480], + 1, + null, + [25570] + ); + + $this->assertSame( + [100], + array_column($result['selected_allocations'], 'id') + ); + } } diff --git a/tests/Unit/ProductResourceConfigurationServiceTest.php b/tests/Unit/ProductResourceConfigurationServiceTest.php new file mode 100644 index 0000000..6bb4316 --- /dev/null +++ b/tests/Unit/ProductResourceConfigurationServiceTest.php @@ -0,0 +1,541 @@ +dynamicProduct(); + $configuration = $this->service()->forQuote($product, [ + $options['memory']->id => 4096, + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + ]); + + $this->assertSame(1, $configuration['location_id']); + $this->assertSame([ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 51200, + ], $configuration['resources']); + $this->assertSame($options['memory']->id, $configuration['sliders']['memory']['config_option_id']); + $this->assertSame(1, $configuration['allocation_count']); + $this->assertSame([], $configuration['required_ports']); + $this->assertSame([[ + 'environment_key' => 'SERVER_PORT', + 'requested_port' => null, + 'is_primary' => true, + ]], $configuration['allocation_mappings']); + } + + public function test_decimal_and_off_step_values_are_rejected(): void + { + [$product, $options, $locationChild] = $this->dynamicProduct(); + $base = [ + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + ]; + + foreach (['2048.5', 1536] as $forgedValue) { + try { + $this->service()->forQuote( + $product, + [$options['memory']->id => $forgedValue] + $base + ); + $this->fail('Expected forged slider value to be rejected.'); + } catch (InvalidResourceSelectionException $exception) { + $this->assertStringContainsString('memory', strtolower($exception->getMessage())); + } + } + } + + public function test_location_must_be_a_child_of_products_location_option(): void + { + [$product, $options] = $this->dynamicProduct(); + $foreignChild = ConfigOption::create([ + 'name' => 'Foreign', + 'env_variable' => '99', + 'type' => 'select', + 'sort' => 0, + 'hidden' => false, + 'upgradable' => false, + 'parent_id' => null, + ]); + + $this->expectException(InvalidResourceSelectionException::class); + + $this->service()->forQuote($product, [ + $options['memory']->id => 4096, + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $foreignChild->id, + ]); + } + + public function test_hidden_location_is_not_quoteable(): void + { + [$product, $options, $locationChild] = $this->dynamicProduct(); + $locationChild->update(['hidden' => true]); + + $this->expectException(InvalidResourceSelectionException::class); + + $this->service()->forQuote($product, [ + $options['memory']->id => 4096, + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + ]); + } + + public function test_hidden_retired_root_options_are_ignored_and_cannot_be_submitted(): void + { + [$product, $options, $locationChild] = $this->dynamicProduct(); + $retiredMemory = $this->slider( + $product, + 'Retired Memory', + 'memory', + 1024, + 65536, + 1024, + 8192 + ); + $retiredLocation = ConfigOption::create([ + 'name' => 'Location', + 'env_variable' => 'location', + 'type' => 'select', + 'sort' => 10, + 'hidden' => false, + 'upgradable' => false, + ]); + DB::table('config_option_products')->insert([ + 'product_id' => $product->id, + 'config_option_id' => $retiredLocation->id, + ]); + + // Simulate the checkout product being loaded before a wizard rerun + // retires obsolete options. The resolver must use current DB state. + $product->load('configOptions.children'); + $retiredMemory->update(['hidden' => true]); + $retiredLocation->update(['hidden' => true]); + + $activeSelection = [ + $options['memory']->id => 4096, + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + ]; + + $configuration = $this->service()->forQuote($product, $activeSelection); + + $this->assertSame(4096, $configuration['resources']['memory']); + $this->assertSame( + $options['memory']->id, + $configuration['sliders']['memory']['config_option_id'] + ); + $this->assertSame(1, $configuration['location_id']); + + foreach ([ + $retiredMemory->id => 8192, + $retiredLocation->id => $locationChild->id, + ] as $retiredOptionId => $value) { + try { + $this->service()->forQuote( + $product, + $activeSelection + [$retiredOptionId => $value] + ); + $this->fail('Expected a retired option submission to be rejected.'); + } catch (InvalidResourceSelectionException $exception) { + $this->assertStringContainsString( + 'not available', + strtolower($exception->getMessage()) + ); + } + } + } + + public function test_attached_child_option_cannot_be_submitted_as_a_root_option(): void + { + [$product, $options, $locationChild] = $this->dynamicProduct(); + DB::table('config_option_products')->insert([ + 'product_id' => $product->id, + 'config_option_id' => $locationChild->id, + ]); + + $this->expectException(InvalidResourceSelectionException::class); + $this->expectExceptionMessage('not available'); + + $this->service()->forQuote($product, [ + $options['memory']->id => 4096, + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + $locationChild->id => 1, + ]); + } + + public function test_overflowing_selection_is_rejected_before_cast(): void + { + [$product, $options, $locationChild] = $this->dynamicProduct(); + + $this->expectException(InvalidResourceSelectionException::class); + + $this->service()->forQuote($product, [ + $options['memory']->id => '999999999999999999999999999999', + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + ]); + } + + public function test_non_empty_port_mapping_requires_server_port(): void + { + [$product, $options, $locationChild] = $this->dynamicProduct(); + $product->settings()->create([ + 'key' => 'port_array', + 'value' => json_encode(['QUERY_PORT' => 25566]), + ]); + + $this->expectException( + \Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException::class + ); + $this->expectExceptionMessage('SERVER_PORT'); + + $this->service()->forQuote($product, [ + $options['memory']->id => 4096, + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + ]); + } + + public function test_port_mapping_preserves_environment_and_primary_identity(): void + { + [$product, $options, $locationChild] = $this->dynamicProduct(); + $product->settings()->create([ + 'key' => 'port_array', + 'value' => json_encode([ + 'SERVER_PORT' => 25570, + 'QUERY_PORT' => 25571, + 'NONE' => [25572, 25573], + ]), + ]); + + $configuration = $this->service()->forQuote($product, [ + $options['memory']->id => 4096, + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + ]); + + $this->assertSame(4, $configuration['allocation_count']); + $this->assertSame( + [25570, 25571, 25572, 25573], + $configuration['required_ports'] + ); + $this->assertSame([ + [ + 'environment_key' => 'SERVER_PORT', + 'requested_port' => 25570, + 'is_primary' => true, + ], + [ + 'environment_key' => 'QUERY_PORT', + 'requested_port' => 25571, + 'is_primary' => false, + ], + [ + 'environment_key' => 'NONE', + 'requested_port' => 25572, + 'is_primary' => false, + ], + [ + 'environment_key' => 'NONE', + 'requested_port' => 25573, + 'is_primary' => false, + ], + ], $configuration['allocation_mappings']); + } + + public function test_port_mapping_rejects_multiple_ports_for_one_egg_environment_key(): void + { + [$product, $options, $locationChild] = $this->dynamicProduct(); + $product->settings()->create([ + 'key' => 'port_array', + 'value' => json_encode([ + 'SERVER_PORT' => 25570, + 'QUERY_PORT' => [25571, 25572], + ]), + ]); + + $this->expectException( + \Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException::class + ); + $this->expectExceptionMessage( + 'may assign exactly one port to QUERY_PORT' + ); + + $this->service()->forQuote($product, [ + $options['memory']->id => 4096, + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + ]); + } + + public function test_additional_allocations_are_preclaimed_without_fake_environment_keys(): void + { + [$product, $options, $locationChild] = $this->dynamicProduct(); + $product->settings()->create([ + 'key' => 'additional_allocations', + 'value' => '2', + ]); + + $configuration = $this->service()->forQuote($product, [ + $options['memory']->id => 4096, + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + ]); + + $this->assertSame(3, $configuration['allocation_count']); + $this->assertSame([ + [ + 'environment_key' => 'SERVER_PORT', + 'requested_port' => null, + 'is_primary' => true, + ], + [ + 'environment_key' => 'NONE', + 'requested_port' => null, + 'is_primary' => false, + ], + [ + 'environment_key' => 'NONE', + 'requested_port' => null, + 'is_primary' => false, + ], + ], $configuration['allocation_mappings']); + } + + public function test_dedicated_ip_and_port_ranges_are_strictly_normalized(): void + { + [$product, $options, $locationChild] = $this->dynamicProduct(); + $product->settings()->create([ + 'key' => 'dedicated_ip', + 'value' => 'true', + ]); + $product->settings()->create([ + 'key' => 'port_range', + 'value' => json_encode([ + '25580-25590', + '25565', + '25566-25579', + ]), + ]); + + $configuration = $this->service()->forQuote($product, [ + $options['memory']->id => 4096, + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + ]); + + $this->assertTrue($configuration['dedicated_ip']); + $this->assertSame([ + ['from' => 25565, 'to' => 25590], + ], $configuration['allowed_port_ranges']); + } + + public function test_port_array_cannot_silently_bypass_deployment_constraints(): void + { + [$product, $options, $locationChild] = $this->dynamicProduct(); + $product->settings()->createMany([ + [ + 'key' => 'port_array', + 'value' => json_encode(['SERVER_PORT' => 25565]), + ], + ['key' => 'dedicated_ip', 'value' => '1'], + ]); + + $this->expectException( + \Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException::class + ); + $this->expectExceptionMessage('cannot combine'); + + $this->service()->forQuote($product, [ + $options['memory']->id => 4096, + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + ]); + } + + public function test_static_node_and_cpu_pinning_cannot_bypass_dynamic_placement(): void + { + foreach ([ + ['key' => 'node', 'value' => '12', 'message' => 'must not be pinned'], + [ + 'key' => 'cpu_pinning', + 'value' => '0,2-3', + 'message' => 'CPU pinning', + ], + ] as $case) { + [$product, $options, $locationChild] = $this->dynamicProduct(); + $product->settings()->create([ + 'key' => $case['key'], + 'value' => $case['value'], + ]); + + try { + $this->service()->forQuote($product, [ + $options['memory']->id => 4096, + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + ]); + $this->fail( + "Expected {$case['key']} to fail dynamic stock closed." + ); + } catch ( + \Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException + $exception + ) { + $this->assertStringContainsString( + $case['message'], + $exception->getMessage() + ); + } + } + } + + public function test_unconfirmed_exclusive_provisioning_control_fails_quote_configuration(): void + { + [$product, $options, $locationChild] = $this->dynamicProduct(); + $inventory = Mockery::mock(PterodactylInventoryService::class); + $inventory->shouldReceive('panelIdentity') + ->andReturn(hash('sha256', 'https://panel.example.com')); + $inventory->shouldReceive('assertExclusiveProvisioningControl') + ->once() + ->andThrow(new \RuntimeException('exclusive pool required')); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('exclusive pool required'); + + (new ProductResourceConfigurationService($inventory))->forQuote($product, [ + $options['memory']->id => 4096, + $options['cpu']->id => 200, + $options['disk']->id => 51200, + $options['location']->id => $locationChild->id, + ]); + } + + private function service(): ProductResourceConfigurationService + { + $inventory = Mockery::mock(PterodactylInventoryService::class); + $inventory->shouldReceive('panelIdentity') + ->zeroOrMoreTimes() + ->andReturn(hash('sha256', 'https://panel.example.com')); + $inventory->shouldReceive('assertExclusiveProvisioningControl') + ->zeroOrMoreTimes(); + + return new ProductResourceConfigurationService($inventory); + } + + /** + * @return array{Product, array, ConfigOption} + */ + private function dynamicProduct(): array + { + $server = Server::create([ + 'name' => 'Pterodactyl', + 'extension' => 'Pterodactyl', + 'type' => 'server', + 'enabled' => true, + ]); + $server->settings()->create([ + 'key' => 'host', + 'value' => 'https://panel.example.com/', + ]); + $product = Product::factory()->create([ + 'server_id' => $server->id, + 'hidden' => false, + ]); + + $options = [ + 'memory' => $this->slider($product, 'Memory', 'memory', 1024, 32768, 1024, 4096), + 'cpu' => $this->slider($product, 'CPU', 'cpu', 100, 1600, 100, 200), + 'disk' => $this->slider($product, 'Disk', 'disk', 10240, 512000, 10240, 51200), + ]; + $options['location'] = ConfigOption::create([ + 'name' => 'Location', + 'env_variable' => 'location', + 'type' => 'select', + 'sort' => 3, + 'hidden' => false, + 'upgradable' => false, + ]); + $locationChild = ConfigOption::create([ + 'name' => 'Melbourne', + 'env_variable' => '1', + 'type' => 'select', + 'sort' => 0, + 'hidden' => false, + 'upgradable' => false, + 'parent_id' => $options['location']->id, + ]); + DB::table('config_option_products')->insert([ + 'product_id' => $product->id, + 'config_option_id' => $options['location']->id, + ]); + + return [$product, $options, $locationChild]; + } + + private function slider( + Product $product, + string $name, + string $resource, + int $minimum, + int $maximum, + int $step, + int $default + ): ConfigOption { + $option = ConfigOption::create([ + 'name' => $name, + 'env_variable' => strtoupper($resource), + 'type' => 'dynamic_slider', + 'sort' => 0, + 'hidden' => false, + 'upgradable' => false, + 'metadata' => [ + 'resource_type' => $resource, + 'min' => $minimum, + 'max' => $maximum, + 'step' => $step, + 'default' => $default, + ], + ]); + DB::table('config_option_products')->insert([ + 'product_id' => $product->id, + 'config_option_id' => $option->id, + ]); + + return $option; + } +} diff --git a/tests/Unit/PterodactylInventoryServiceTest.php b/tests/Unit/PterodactylInventoryServiceTest.php new file mode 100644 index 0000000..3ccaced --- /dev/null +++ b/tests/Unit/PterodactylInventoryServiceTest.php @@ -0,0 +1,445 @@ +inventory = new PterodactylInventoryService([ + 'pterodactyl_url' => 'https://panel.example.com/', + 'pterodactyl_api_key' => 'application-key', + 'exclusive_provisioning_control' => true, + ]); + } + + public function test_panel_identity_preserves_case_sensitive_path(): void + { + $inventory = new PterodactylInventoryService([ + 'pterodactyl_url' => + 'HTTPS://Panel.Example.com:443/PanelA/', + 'pterodactyl_api_key' => 'application-key', + 'exclusive_provisioning_control' => true, + ]); + + $this->assertSame( + PanelEndpointIdentity::hash( + 'https://panel.example.com/PanelA' + ), + $inventory->panelIdentity() + ); + $this->assertNotSame( + PanelEndpointIdentity::hash( + 'https://panel.example.com/panela' + ), + $inventory->panelIdentity() + ); + } + + public function test_nodes_are_paginated_and_location_is_filtered_locally(): void + { + Http::fake(function ($request) { + $query = []; + parse_str(parse_url($request->url(), PHP_URL_QUERY) ?? '', $query); + $this->assertArrayNotHasKey('filter', $query); + $this->assertSame('allocations', $query['include'] ?? null); + $page = (int) ($query['page'] ?? 1); + + return Http::response([ + 'data' => $page === 1 + ? [$this->nodeResource(10, 1), $this->nodeResource(20, 2)] + : [$this->nodeResource(30, 1)], + 'meta' => ['pagination' => [ + 'current_page' => $page, + 'total_pages' => 2, + ]], + ]); + }); + + $nodes = $this->inventory->nodesInLocation(1); + + $this->assertSame([10, 30], array_column($nodes, 'id')); + $this->assertSame( + ['memory' => 1024, 'disk' => 2048], + $nodes[0]['allocated_resources'] + ); + $this->assertSame( + [10001], + array_column( + $this->inventory->availableAllocationsForNode(10), + 'id' + ) + ); + $this->assertSame( + [30001], + array_column( + $this->inventory->availableAllocationsForNode(30), + 'id' + ) + ); + Http::assertSentCount(2); + } + + public function test_locations_use_stock_application_api_shape(): void + { + Http::fake([ + '*' => Http::response(['data' => [[ + 'object' => 'location', + 'attributes' => [ + 'id' => 1, + 'short' => 'mel', + 'long' => 'Melbourne', + ], + ]]]), + ]); + + $this->assertSame([[ + 'id' => 1, + 'short' => 'mel', + 'long' => 'Melbourne', + ]], $this->inventory->locations()); + } + + public function test_free_allocation_reports_when_its_ip_is_already_assigned(): void + { + $node = $this->nodeResource(10, 1); + $node['relationships']['allocations']['data'][] = + $this->allocationResource(10002, true); + + Http::fake([ + '*' => Http::response(['data' => [$node]]), + ]); + + $allocations = $this->inventory->nodes()[0]['available_allocations']; + + $this->assertCount(1, $allocations); + $this->assertSame(10001, $allocations[0]['id']); + $this->assertTrue($allocations[0]['ip_in_use']); + } + + public function test_server_and_allocation_shapes_are_read_without_optimistic_defaults(): void + { + Http::fake(function ($request) { + $query = []; + parse_str(parse_url($request->url(), PHP_URL_QUERY) ?? '', $query); + $page = (int) ($query['page'] ?? 1); + + if (str_contains($request->url(), '/servers/external/paymenter-44')) { + return Http::response($this->serverResource( + 44, + 10, + memory: 4096, + cpu: 200, + disk: 20480, + allocation: 501 + )); + } + + if (str_contains($request->url(), '/api/application/users/44')) { + return Http::response([ + 'object' => 'user', + 'attributes' => [ + 'id' => 44, + 'external_id' => 'paymenter-user-30', + 'email' => 'customer@example.com', + ], + ]); + } + + if (str_contains($request->url(), '/api/application/servers')) { + $this->assertSame('allocations', $query['include'] ?? null); + + return Http::response([ + 'data' => $page === 1 + ? [$this->serverResource(44, 10, 4096, 200, 20480, 501)] + : [$this->serverResource(45, 10, 2048, 100, 10240, 502)], + 'meta' => ['pagination' => [ + 'current_page' => $page, + 'total_pages' => 2, + ]], + ]); + } + + if (str_contains($request->url(), '/nodes/10/allocations')) { + return Http::response([ + 'data' => $page === 1 + ? [ + $this->allocationResource(501, true), + $this->allocationResource(502, false), + ] + : [$this->allocationResource(503, false)], + 'meta' => ['pagination' => [ + 'current_page' => $page, + 'total_pages' => 2, + ]], + ]); + } + + return Http::response([], 404); + }); + + $servers = $this->inventory->serversForNodes([10]); + $allocations = $this->inventory->availableAllocationsForNode(10); + $external = $this->inventory->serverByExternalId('paymenter-44'); + + $this->assertSame([ + 'id' => 44, + 'uuid' => '10000000-0000-4000-8000-000000000044', + 'identifier' => 'server-44', + 'external_id' => '44', + 'node' => 10, + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + 'allocation_limit' => 1, + 'assigned_allocation_ids' => [501], + 'allocation_headroom' => 0, + ], $servers[10][0]); + $this->assertSame([44, 45], array_column($servers[10], 'id')); + $this->assertSame([502, 503], array_column($allocations, 'id')); + $this->assertSame(501, $external['allocation']); + $this->assertSame([501], $external['assigned_allocation_ids']); + $this->assertSame('paymenter-user-30', $external['user_external_id']); + $this->assertSame('customer@example.com', $external['user_email']); + $this->assertSame(1, $external['nest_id']); + $this->assertSame(2, $external['egg_id']); + } + + public function test_missing_overallocation_field_fails_inventory_closed(): void + { + $node = $this->nodeResource(10, 1); + unset($node['attributes']['memory_overallocate']); + + Http::fake([ + '*' => Http::response(['data' => [$node]]), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('memory_overallocate'); + + $this->inventory->nodes(); + } + + public function test_integer_overflow_is_rejected_instead_of_saturated(): void + { + $node = $this->nodeResource(10, 1); + $node['attributes']['memory'] = '999999999999999999999999999999'; + + Http::fake([ + '*' => Http::response(['data' => [$node]]), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('supported integer range'); + + $this->inventory->nodes(); + } + + public function test_customer_allocation_headroom_is_derived_from_assigned_relationship(): void + { + $server = $this->serverResource(44, 10, 4096, 200, 20480, 501); + $server['attributes']['feature_limits']['allocations'] = 2; + + Http::fake([ + '*' => Http::response(['data' => [$server]]), + ]); + + $inventory = $this->inventory->serversForNodes([10])[10][0]; + + $this->assertSame(2, $inventory['allocation_limit']); + $this->assertSame([501], $inventory['assigned_allocation_ids']); + $this->assertSame(1, $inventory['allocation_headroom']); + } + + public function test_missing_server_allocation_relationship_fails_inventory_closed(): void + { + $server = $this->serverResource(44, 10, 4096, 200, 20480, 501); + unset($server['relationships']); + + Http::fake([ + '*' => Http::response(['data' => [$server]]), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('allocations relationship'); + + $this->inventory->serversForNodes([10]); + } + + public function test_missing_server_identity_fails_snapshot_proof_closed(): void + { + $server = $this->serverResource(44, 10, 4096, 200, 20480, 501); + unset($server['attributes']['uuid']); + + Http::fake([ + '*' => Http::response(['data' => [$server]]), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('server.uuid'); + + $this->inventory->serversForNodes([10]); + } + + public function test_connection_check_exercises_nodes_servers_and_allocations_permissions(): void + { + $paths = []; + $nodeIncludes = []; + + Http::fake(function ($request) use (&$paths, &$nodeIncludes) { + $paths[] = parse_url($request->url(), PHP_URL_PATH); + + if (str_ends_with(parse_url($request->url(), PHP_URL_PATH), '/nodes')) { + $query = []; + parse_str( + parse_url($request->url(), PHP_URL_QUERY) ?? '', + $query + ); + $nodeIncludes[] = $query['include'] ?? null; + + return Http::response(['data' => [$this->nodeResource(10, 1)]]); + } + if (str_ends_with(parse_url($request->url(), PHP_URL_PATH), '/servers')) { + return Http::response(['data' => []]); + } + if (str_contains($request->url(), '/nodes/10/allocations')) { + return Http::response(['data' => [$this->allocationResource(502, false)]]); + } + + return Http::response([], 404); + }); + + $result = $this->inventory->testConnection(); + + $this->assertTrue($result['success']); + $this->assertContains('/api/application/nodes', $paths); + $this->assertContains('/api/application/servers', $paths); + $this->assertSame(['allocations'], $nodeIncludes); + $this->assertNotContains( + '/api/application/nodes/10/allocations', + $paths, + 'The included allocation snapshot must avoid an N+1 node scan.' + ); + } + + public function test_legacy_allocation_only_acknowledgement_is_not_a_capacity_guarantee(): void + { + $inventory = new PterodactylInventoryService([ + 'pterodactyl_url' => 'https://panel.example.com', + 'pterodactyl_api_key' => 'application-key', + 'exclusive_allocation_pool' => true, + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('exclusive provisioning control'); + + $inventory->assertExclusiveProvisioningControl(); + } + + private function nodeResource(int $id, int $locationId): array + { + return [ + 'object' => 'node', + 'attributes' => [ + 'id' => $id, + 'uuid' => sprintf('00000000-0000-4000-8000-%012d', $id), + 'name' => 'Node '.$id, + 'fqdn' => 'node-'.$id.'.example.com', + 'public' => true, + 'maintenance_mode' => false, + 'location_id' => $locationId, + 'memory' => 32768, + 'disk' => 512000, + 'memory_overallocate' => 0, + 'disk_overallocate' => 0, + 'allocated_resources' => [ + 'memory' => 1024, + 'disk' => 2048, + ], + ], + 'relationships' => [ + 'allocations' => [ + 'data' => [ + $this->allocationResource( + ($id * 1000) + 1, + false + ), + ], + ], + ], + ]; + } + + private function serverResource( + int $id, + int $node, + int $memory, + int $cpu, + int $disk, + int $allocation + ): array { + return [ + 'object' => 'server', + 'attributes' => [ + 'id' => $id, + 'uuid' => sprintf( + '10000000-0000-4000-8000-%012d', + $id + ), + 'identifier' => 'server-'.$id, + 'external_id' => (string) $id, + 'user' => 44, + 'nest' => 1, + 'egg' => 2, + 'node' => $node, + 'allocation' => $allocation, + 'feature_limits' => [ + 'databases' => 2, + 'allocations' => 1, + 'backups' => 3, + ], + 'limits' => [ + 'memory' => $memory, + 'cpu' => $cpu, + 'disk' => $disk, + 'swap' => 0, + 'io' => 500, + 'threads' => null, + ], + ], + 'relationships' => [ + 'allocations' => [ + 'data' => [[ + 'object' => 'allocation', + 'attributes' => [ + 'id' => $allocation, + ], + ]], + ], + ], + ]; + } + + private function allocationResource(int $id, bool $assigned): array + { + return [ + 'object' => 'allocation', + 'attributes' => [ + 'id' => $id, + 'ip' => '192.0.2.10', + 'port' => 25000 + $id, + 'assigned' => $assigned, + ], + ]; + } +} diff --git a/tests/Unit/ReservationConfigurationServiceTest.php b/tests/Unit/ReservationConfigurationServiceTest.php index 62ecf8d..e809b04 100644 --- a/tests/Unit/ReservationConfigurationServiceTest.php +++ b/tests/Unit/ReservationConfigurationServiceTest.php @@ -2,11 +2,47 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; +use App\Models\Product; +use App\Models\Service; +use App\Support\PanelEndpointIdentity; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationConfigurationService; use PHPUnit\Framework\TestCase; class ReservationConfigurationServiceTest extends TestCase { + public function test_checkout_panel_normalization_matches_shared_identity_without_path_collision(): void + { + $normalizer = new \ReflectionMethod( + ReservationConfigurationService::class, + 'normalizePanelUrl' + ); + $normalizer->setAccessible(true); + $service = new ReservationConfigurationService; + $canonical = $normalizer->invoke( + $service, + 'HTTPS://Panel.Example.com:443/PanelA/' + ); + $differentPath = $normalizer->invoke( + $service, + 'https://panel.example.com/panela' + ); + + $this->assertSame( + PanelEndpointIdentity::canonicalUrl( + 'https://panel.example.com/PanelA' + ), + $canonical + ); + $this->assertNotSame($canonical, $differentPath); + $this->assertSame( + '', + $normalizer->invoke( + $service, + 'https://panel.example.com/PanelA?token=secret' + ) + ); + } + public function test_fingerprint_is_stable_for_equivalent_key_order(): void { $service = new ReservationConfigurationService; @@ -62,7 +98,93 @@ public function test_resource_or_node_change_changes_fingerprint(): void $guestPayload = $service->withNode(array_replace($snapshot, ['customer_id' => null]), 3); $this->assertNotSame( $service->fingerprint($guestPayload), - $service->fingerprint($service->withCustomer($guestPayload, 30)) + $service->fingerprint($service->withCustomer( + $guestPayload, + 30, + 'Customer@Example.com' + )) ); } + + public function test_bound_service_uses_snapshot_when_product_defaults_change(): void + { + $configuration = new ReservationConfigurationService; + $payload = [ + 'customer_id' => 30, + 'cart_id' => 1, + 'server_extension_id' => 5, + 'panel_identity' => str_repeat('c', 64), + 'product_id' => 10, + 'plan_id' => 20, + 'quantity' => 1, + 'currency_code' => 'AUD', + 'location_id' => 2, + 'node_id' => 3, + 'resources' => [ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 51200, + ], + 'provisioning_identity' => [ + 'nest_id' => 1, + 'egg_id' => 2, + 'user_external_id' => 'paymenter-user-30', + 'user_email' => 'customer@example.com', + ], + 'config_options' => [], + 'allocations' => [[ + 'allocation_id' => 91, + 'ip' => '192.0.2.10', + 'port' => 25565, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ]], + ]; + $service = new Service; + $service->setRawAttributes([ + 'id' => 40, + 'user_id' => 30, + 'product_id' => 10, + 'plan_id' => 20, + 'quantity' => 1, + 'currency_code' => 'AUD', + ], true); + $service->exists = true; + $service->setRelation('user', new \App\Models\User([ + 'id' => 30, + 'email' => 'renamed@example.com', + ])); + // These mutable defaults deliberately disagree with the hold. They + // must not reprice or invalidate the already-promised capacity. + $service->setRelation('product', new Product([ + 'server_id' => 999, + 'memory' => 65536, + 'cpu' => 900, + 'disk' => 999999, + ])); + $reservation = (object) [ + 'service_id' => 40, + 'user_id' => 30, + 'server_extension_id' => 5, + 'panel_identity' => str_repeat('c', 64), + 'product_id' => 10, + 'plan_id' => 20, + 'quantity' => 1, + 'currency_code' => 'AUD', + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 51200, + 'location_id' => 2, + 'node_id' => 3, + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + 'configuration_fingerprint' => $configuration->fingerprint($payload), + ]; + + $configuration->assertServiceMatches($service, $reservation); + + $this->addToAssertionCount(1); + } } diff --git a/tests/Unit/ReservationServiceTest.php b/tests/Unit/ReservationServiceTest.php index 8574549..78d2bcc 100644 --- a/tests/Unit/ReservationServiceTest.php +++ b/tests/Unit/ReservationServiceTest.php @@ -2,12 +2,32 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; +use App\Jobs\Server\CreateJob; +use App\Jobs\Server\SuspendJob; +use App\Helpers\ExtensionHelper; +use App\Models\ConfigOption; +use App\Models\Extension; +use App\Models\Invoice; +use App\Models\Product; +use App\Models\Server; use App\Models\Service; use App\Models\User; +use App\Services\Extensions\ExtensionLifecycleGuard; +use App\Services\Invoice\CancelInvoiceService; +use App\Services\Invoice\MarkInvoicePaidService; +use App\Services\Service\DurableFulfillmentService; +use App\Services\Service\FulfillmentStatusTransitionService; +use App\Services\Service\RenewServiceService; +use Carbon\Carbon; use Illuminate\Database\QueryException; use Illuminate\Foundation\Testing\DatabaseTransactions; +use Illuminate\Support\Facades\Artisan; +use Illuminate\Support\Facades\Bus; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Queue; +use Illuminate\Support\Str; use Mockery; +use Paymenter\Extensions\Others\DynamicPterodactyl\Models\ResourceReservation; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AuditLogService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\NodeSelectionService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationConfigurationService; @@ -72,126 +92,1918 @@ public function test_only_one_pending_hold_may_use_a_cart_item_guard(): void $this->insertReservation(cartItemGuardId: 42); } - public function test_begin_keeps_hold_pending_until_complete_consumes_it(): void + public function test_only_one_active_checkout_commitment_may_use_a_service(): void { $service = $this->makeService(); - $reservationId = $this->insertReservation(serviceId: $service->id, userId: $service->user_id); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed' + ); + + $this->expectException(QueryException::class); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'confirmed' + ); + } + + public function test_only_one_active_upgrade_commitment_may_use_an_upgrade_guard(): void + { + $this->insertReservation( + status: 'paid_committed', + purpose: 'upgrade', + upgradeGuardId: 991 + ); + + $this->expectException(QueryException::class); + $this->insertReservation( + status: 'pending', + purpose: 'upgrade', + upgradeGuardId: 991 + ); + } + + public function test_only_one_active_hold_may_claim_an_allocation(): void + { + $first = $this->insertReservation(); + $second = $this->insertReservation(); + $this->insertAllocation($first, 7001); + + $this->expectException(QueryException::class); + $this->insertAllocation($second, 7001); + } + + public function test_reservation_snapshot_is_built_under_the_configuration_lock(): void + { + $source = file_get_contents( + __DIR__ . '/../../Services/ReservationService.php' + ); + $method = strpos( + $source, + 'public function reserveForCartItem' + ); + $transaction = strpos( + $source, + 'return DB::transaction', + $method + ); + $configurationLock = strpos( + $source, + '->lockProduct(', + $transaction + ); + $snapshot = strpos( + $source, + '->forCartItem($cartItem)', + $configurationLock + ); + $insert = strpos( + $source, + "DB::table('ptero_resource_reservations')->insertGetId", + $snapshot + ); + + $this->assertNotFalse($method); + $this->assertNotFalse($transaction); + $this->assertNotFalse($configurationLock); + $this->assertNotFalse($snapshot); + $this->assertNotFalse($insert); + $this->assertLessThan($configurationLock, $transaction); + $this->assertLessThan($snapshot, $configurationLock); + $this->assertLessThan($insert, $snapshot); + $this->assertFalse( + strpos( + substr($source, $method, $transaction - $method), + '->forCartItem(' + ), + 'No mutable configuration snapshot may be built before the transaction.' + ); + } + + public function test_checkout_binding_uses_global_capacity_invoice_lock_order(): void + { + $source = file_get_contents( + __DIR__ . '/../../Services/ReservationService.php' + ); + $method = strpos( + $source, + 'public function bindCartItemToService' + ); + $nextMethod = strpos( + $source, + 'public function preflightPaidService', + $method + ); + $body = substr($source, $method, $nextMethod - $method); + $invoice = strpos($body, '$lockedInvoice = Invoice::query()'); + $service = strpos($body, '$lockedService = Service::query()'); + $reservation = strpos( + $body, + "DB::table('ptero_resource_reservations')" + ); + $items = strpos($body, "DB::table('invoice_items')"); + + $this->assertNotFalse($invoice); + $this->assertNotFalse($service); + $this->assertNotFalse($reservation); + $this->assertNotFalse($items); + $this->assertLessThan($service, $invoice); + $this->assertLessThan($reservation, $service); + $this->assertLessThan($items, $reservation); + } + + public function test_active_commitment_blocks_extension_deactivation(): void + { + $this->insertReservation(); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('cannot be disabled, replaced, or uninstalled'); + + app(ExtensionLifecycleGuard::class) + ->assertCanDeactivate(ExtensionLifecycleGuard::DYNAMIC_PTERODACTYL); + } + + public function test_terminal_history_does_not_block_extension_deactivation(): void + { + $this->insertReservation(status: 'cancelled'); + + app(ExtensionLifecycleGuard::class) + ->assertCanDeactivate(ExtensionLifecycleGuard::DYNAMIC_PTERODACTYL); + + $this->addToAssertionCount(1); + } + + public function test_confirmed_active_service_blocks_extension_deactivation(): void + { + $service = $this->makeService(Service::STATUS_ACTIVE); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'confirmed', + consumedAt: now() + ); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage( + 'cannot be disabled, replaced, or uninstalled' + ); + + app(ExtensionLifecycleGuard::class) + ->assertCanDeactivate( + ExtensionLifecycleGuard::DYNAMIC_PTERODACTYL + ); + } + + public function test_confirmed_active_service_allows_same_identity_upgrade_only_in_maintenance(): void + { + $service = $this->makeService(Service::STATUS_ACTIVE); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'confirmed', + consumedAt: now() + ); + $guard = app(ExtensionLifecycleGuard::class); + + try { + $guard->assertCanUpgrade( + ExtensionLifecycleGuard::DYNAMIC_PTERODACTYL + ); + $this->fail( + 'Live durable services must require deployment maintenance.' + ); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'deployment maintenance', + $exception->getMessage() + ); + } + + Artisan::call('down'); + try { + $guard->assertCanUpgrade( + ExtensionLifecycleGuard::DYNAMIC_PTERODACTYL + ); + $this->addToAssertionCount(1); + } finally { + Artisan::call('up'); + } + } + + public function test_pending_commitment_keeps_its_snapshot_while_future_slider_metadata_changes(): void + { + $product = Product::factory()->create(); + $option = $this->resourceOption('Memory', 'memory'); + $option->products()->attach($product->id); + $reservationId = $this->insertReservation(productId: $product->id); + $originalPayload = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('configuration_payload'); + $originalFingerprint = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('configuration_fingerprint'); + + $metadata = $option->metadata; + $metadata['max'] = 200000; + $option->metadata = $metadata; + $option->save(); + + $this->assertSame(200000, $option->fresh()->metadata['max']); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'pending', + 'configuration_payload' => $originalPayload, + 'configuration_fingerprint' => $originalFingerprint, + ]); + } + + public function test_pending_commitment_keeps_its_snapshot_while_future_child_price_changes(): void + { + $product = Product::factory()->create(); + $root = ConfigOption::create([ + 'name' => 'Location', + 'env_variable' => 'location', + 'type' => 'select', + 'hidden' => false, + 'upgradable' => false, + ]); + $root->products()->attach($product->id); + $child = ConfigOption::create([ + 'name' => 'Melbourne', + 'env_variable' => 'location', + 'type' => 'select', + 'hidden' => false, + 'upgradable' => false, + 'parent_id' => $root->id, + ]); + $plan = $child->plans()->create([ + 'name' => 'Monthly', + 'type' => 'recurring', + 'billing_period' => 1, + 'billing_unit' => 'month', + ]); + $price = $plan->prices()->create([ + 'currency_code' => 'USD', + 'price' => 5, + 'setup_fee' => 0, + ]); + $this->insertReservation(productId: $product->id); + + $price->price = 7; + $price->save(); + + $this->assertSame('7.00', (string) $price->fresh()->price); + } + + public function test_pending_commitment_prevents_detaching_its_configuration(): void + { + $product = Product::factory()->create(); + $option = $this->resourceOption('Disk', 'disk'); + $option->products()->attach($product->id); + $this->insertReservation(productId: $product->id); + + try { + $option->products()->detach($product->id); + $this->fail('Expected the product assignment to remain frozen.'); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'required by an unresolved or active capacity commitment', + $exception->getMessage() + ); + } + + $this->assertDatabaseHas('config_option_products', [ + 'config_option_id' => $option->id, + 'product_id' => $product->id, + ]); + } + + public function test_pending_commitment_prevents_reassigning_resource_identity(): void + { + $product = Product::factory()->create(); + $option = $this->resourceOption('Memory', 'memory'); + $option->products()->attach($product->id); + $this->insertReservation(productId: $product->id); + + $option->env_variable = 'different_memory'; + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage( + 'required by an unresolved or active capacity commitment' + ); + + $option->save(); + } + + public function test_pending_commitment_prevents_deleting_its_product(): void + { + $product = Product::factory()->create(); + $this->insertReservation(productId: $product->id); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage( + 'required by an unresolved or active capacity commitment' + ); + + $product->delete(); + } + + public function test_confirmed_active_service_keeps_its_configuration_identity(): void + { + $product = Product::factory()->create(); + $option = $this->resourceOption('Disk', 'disk'); + $option->products()->attach($product->id); + $service = $this->makeService(Service::STATUS_ACTIVE); + DB::table('services')->where('id', $service->id)->update([ + 'product_id' => $product->id, + ]); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + productId: $product->id, + status: 'confirmed', + consumedAt: now() + ); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage( + 'required by an unresolved or active capacity commitment' + ); + + $option->products()->detach($product->id); + } + + public function test_confirmed_cancelled_service_releases_configuration_identity(): void + { + $product = Product::factory()->create(); + $option = $this->resourceOption('Disk', 'disk'); + $option->products()->attach($product->id); + $service = $this->makeService(Service::STATUS_CANCELLED); + DB::table('services')->where('id', $service->id)->update([ + 'product_id' => $product->id, + ]); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + productId: $product->id, + status: 'confirmed', + consumedAt: now() + ); + + $option->products()->detach($product->id); + + $this->assertDatabaseMissing('config_option_products', [ + 'config_option_id' => $option->id, + 'product_id' => $product->id, + ]); + } + + public function test_dynamic_slider_cannot_be_attached_to_product_with_unmigrated_live_service(): void + { + $product = $this->pterodactylProduct(); + $service = $this->makeService(Service::STATUS_ACTIVE); + DB::table('services')->where('id', $service->id)->update([ + 'product_id' => $product->id, + ]); + $option = $this->resourceOption('Memory', 'memory'); + + try { + $option->products()->attach($product->id); + $this->fail('Expected legacy service conversion to be rejected.'); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'has no confirmed checkout reservation', + $exception->getMessage() + ); + } + + $this->assertDatabaseMissing('config_option_products', [ + 'config_option_id' => $option->id, + 'product_id' => $product->id, + ]); + } + + public function test_attached_option_cannot_be_activated_as_dynamic_for_unmigrated_live_service(): void + { + $product = $this->pterodactylProduct(); + $service = $this->makeService(Service::STATUS_ACTIVE); + DB::table('services')->where('id', $service->id)->update([ + 'product_id' => $product->id, + ]); + $option = ConfigOption::create([ + 'name' => 'Memory', + 'env_variable' => 'memory', + 'type' => 'number', + 'hidden' => false, + 'upgradable' => false, + 'metadata' => ['resource_type' => 'memory'], + ]); + $option->products()->attach($product->id); + $option->type = 'dynamic_slider'; + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage( + 'has no confirmed checkout reservation' + ); + + $option->save(); + } + + public function test_product_with_dynamic_slider_cannot_switch_to_pterodactyl_with_unmigrated_live_service(): void + { + $legacyHost = Server::query()->create([ + 'name' => 'Legacy host', + 'extension' => 'LegacyHost', + 'type' => 'server', + 'enabled' => true, + ]); + $pterodactyl = Server::query()->create([ + 'name' => 'Pterodactyl', + 'extension' => 'Pterodactyl', + 'type' => 'server', + 'enabled' => true, + ]); + $product = Product::factory()->create([ + 'server_id' => $legacyHost->id, + ]); + $option = $this->resourceOption('Memory', 'memory'); + $option->products()->attach($product->id); + $service = $this->makeService(Service::STATUS_ACTIVE); + DB::table('services')->where('id', $service->id)->update([ + 'product_id' => $product->id, + ]); + $product->server_id = $pterodactyl->id; + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage( + 'has no confirmed checkout reservation' + ); + + $product->save(); + } + + public function test_confirmed_service_allows_future_dynamic_slider_attachment(): void + { + $product = $this->pterodactylProduct(); + $service = $this->makeService(Service::STATUS_ACTIVE); + DB::table('services')->where('id', $service->id)->update([ + 'product_id' => $product->id, + ]); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'confirmed', + consumedAt: now(), + productId: $product->id + ); + $option = $this->resourceOption('CPU', 'cpu'); + + $option->products()->attach($product->id); + + $this->assertDatabaseHas('config_option_products', [ + 'config_option_id' => $option->id, + 'product_id' => $product->id, + ]); + } + + public function test_cancelled_legacy_service_allows_dynamic_slider_attachment(): void + { + $product = $this->pterodactylProduct(); + $service = $this->makeService(Service::STATUS_CANCELLED); + DB::table('services')->where('id', $service->id)->update([ + 'product_id' => $product->id, + ]); + $option = $this->resourceOption('Disk', 'disk'); + + $option->products()->attach($product->id); + + $this->assertDatabaseHas('config_option_products', [ + 'config_option_id' => $option->id, + 'product_id' => $product->id, + ]); + } + + public function test_fulfilled_history_allows_future_configuration_changes(): void + { + $product = Product::factory()->create(); + $option = $this->resourceOption('CPU', 'cpu'); + $option->products()->attach($product->id); + $this->insertReservation( + productId: $product->id, + status: 'confirmed', + consumedAt: now() + ); + + $metadata = $option->metadata; + $metadata['max'] = 200000; + $option->metadata = $metadata; + $option->save(); + + $this->assertSame(200000, $option->fresh()->metadata['max']); + } + + public function test_begin_keeps_paid_commitment_reserved_until_verified_completion(): void + { + $service = $this->makeService(); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed' + ); + $this->insertAllocation($reservationId); + + $this->configurationService->shouldReceive('assertServiceMatches') + ->once() + ->with($service, Mockery::on(fn ($row) => (int) $row->id === $reservationId)); + + $context = $this->service()->beginProvisioning($service); + + $this->assertSame(4, $context['node_id']); + $this->assertFalse($context['already_consumed']); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'paid_committed', + ]); + $this->assertNotNull( + DB::table('ptero_resource_reservations')->where('id', $reservationId)->value('provisioning_started_at') + ); + + $this->assertNotNull($context['provisioning_lease_id']); + $this->assertTrue( + $this->service()->completeProvisioning( + $service->id, + $context['provisioning_lease_id'], + $this->externalServer() + ) + ); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'confirmed', + ]); + $this->assertNotNull( + DB::table('ptero_resource_reservations')->where('id', $reservationId)->value('consumed_at') + ); + $this->assertSame('active', $service->fresh()->status); + $this->assertNotNull( + DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservationId) + ->value('released_at') + ); + } + + public function test_active_provisioning_lease_rejects_a_second_worker(): void + { + $service = $this->makeService(); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed', + provisioningStartedAt: now() + ); + $this->insertAllocation($reservationId); + + $this->configurationService->shouldNotReceive('assertServiceMatches'); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('already being provisioned'); + + $this->service()->beginProvisioning($service); + } + + public function test_failed_provisioning_releases_only_the_attempt_lease(): void + { + $service = $this->makeService(); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed', + provisioningStartedAt: now(), + provisioningLeaseId: 'active-lease' + ); + + $this->service()->failProvisioning( + $service->id, + 'active-lease', + new \RuntimeException('Pterodactyl unavailable') + ); + + $reservation = DB::table('ptero_resource_reservations')->where('id', $reservationId)->first(); + $this->assertSame('paid_committed', $reservation->status); + $this->assertNull($reservation->provisioning_started_at); + $this->assertSame('Pterodactyl unavailable', $reservation->last_provisioning_error); + $this->assertNotNull($reservation->next_provisioning_attempt_at); + } + + public function test_stale_worker_cannot_consume_or_clear_a_newer_lease(): void + { + $service = $this->makeService(); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed', + provisioningStartedAt: now(), + provisioningLeaseId: 'new-lease' + ); + + try { + $this->service()->completeProvisioning( + $service->id, + 'old-lease', + $this->externalServer() + ); + $this->fail('Expected stale provisioning lease rejection.'); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString('no longer owns', $exception->getMessage()); + } + + $this->service()->failProvisioning( + $service->id, + 'old-lease', + new \RuntimeException('stale worker failed') + ); + + $reservation = DB::table('ptero_resource_reservations')->where('id', $reservationId)->first(); + $this->assertSame('paid_committed', $reservation->status); + $this->assertSame('new-lease', $reservation->provisioning_lease_id); + $this->assertNotNull($reservation->provisioning_started_at); + $this->assertNull($reservation->last_provisioning_error); + } + + public function test_completed_reservation_is_idempotent_for_server_reconciliation(): void + { + $service = $this->makeService(); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'confirmed', + consumedAt: now() + ); + $reservationId = (int) DB::table('ptero_resource_reservations') + ->where('service_id', $service->id) + ->value('id'); + $this->insertAllocation($reservationId); + + $context = $this->service()->beginProvisioning($service); + + $this->assertTrue($context['already_consumed']); + $this->assertTrue($this->service()->completeProvisioning($service->id)); + } + + public function test_bound_invoice_commits_even_if_current_metadata_no_longer_creates_new_holds(): void + { + $service = $this->makeService(); + $invoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PENDING, + 'currency_code' => 'USD', + ]); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + guaranteedUntil: now()->addDays(7) + ); + $this->insertAllocation($reservationId); + $invoice->items()->create([ + 'reference_type' => Service::class, + 'reference_id' => $service->id, + 'price' => 12.50, + 'quantity' => 1, + 'description' => 'Dynamic service', + ]); + + $this->configurationService->shouldNotReceive('requiresReservation'); + $this->configurationService->shouldReceive('assertExclusiveProvisioningControl')->once(); + $this->configurationService->shouldReceive('assertServiceMatches')->once(); + + $this->assertTrue($this->service()->commitPaidService($service, $invoice)); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'invoice_id' => $invoice->id, + 'status' => 'paid_committed', + ]); + $this->assertSame('provisioning', $service->fresh()->status); + } + + public function test_allocation_drift_rejects_payment_before_capacity_is_committed(): void + { + $service = $this->makeService(); + $invoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PENDING, + 'currency_code' => 'USD', + ]); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + guaranteedUntil: now()->addDays(7) + ); + $this->insertAllocation($reservationId); + DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservationId) + ->update(['port' => 25566]); + $invoice->items()->create([ + 'reference_type' => Service::class, + 'reference_id' => $service->id, + 'price' => 12.50, + 'quantity' => 1, + 'description' => 'Dynamic service', + ]); + + $this->configurationService->shouldNotReceive('requiresReservation'); + $this->configurationService + ->shouldReceive('assertExclusiveProvisioningControl') + ->once(); + $this->configurationService + ->shouldReceive('assertServiceMatches') + ->once(); + + try { + $this->service()->commitPaidService($service, $invoice); + $this->fail( + 'Expected allocation drift to reject payment commitment.' + ); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'Allocation claims no longer match', + $exception->getMessage() + ); + } + + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'pending', + ]); + } + + public function test_non_dynamic_service_does_not_require_stock_control_gate(): void + { + $service = $this->makeService(); + $invoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PENDING, + ]); + $this->configurationService->shouldReceive('requiresReservation') + ->once() + ->with((int) $service->product_id) + ->andReturnFalse(); + $this->configurationService->shouldNotReceive( + 'assertExclusiveProvisioningControl' + ); + + $this->assertFalse( + $this->service()->commitPaidService($service, $invoice) + ); + } + + public function test_tampered_invoice_line_cannot_consume_reserved_capacity(): void + { + $service = $this->makeService(); + $invoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PENDING, + 'currency_code' => 'USD', + ]); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + guaranteedUntil: now()->addDays(7) + ); + $invoice->items()->create([ + 'reference_type' => Service::class, + 'reference_id' => $service->id, + 'price' => 0.01, + 'quantity' => 1, + 'description' => 'Tampered dynamic service', + ]); + + $this->configurationService->shouldNotReceive('requiresReservation'); + $this->configurationService->shouldReceive('assertExclusiveProvisioningControl')->once(); + $this->configurationService->shouldNotReceive('assertServiceMatches'); + + try { + $this->service()->commitPaidService($service, $invoice); + $this->fail('Expected invoice-line drift to reject the payment commitment.'); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'invoice line no longer matches', + $exception->getMessage() + ); + } + + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'pending', + ]); + } + + public function test_payment_after_the_seven_day_guarantee_fails_closed(): void + { + $service = $this->makeService(); + $invoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PENDING, + ]); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + guaranteedUntil: now()->subSecond() + ); + + $this->configurationService->shouldNotReceive('requiresReservation'); + $this->configurationService->shouldReceive('assertExclusiveProvisioningControl')->once(); + $this->configurationService->shouldNotReceive('assertServiceMatches'); + + try { + $this->service()->commitPaidService($service, $invoice); + $this->fail('Expected the expired capacity guarantee to reject payment.'); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString('seven-day capacity guarantee expired', $exception->getMessage()); + } + + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'pending', + ]); + $this->assertSame('pending', $service->fresh()->status); + } + + public function test_completion_requires_a_durable_external_identity(): void + { + $service = $this->makeService(); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed', + provisioningStartedAt: now(), + provisioningLeaseId: 'lease' + ); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('complete external server identity'); + + try { + $this->service()->completeProvisioning($service->id, 'lease', ['attributes' => ['id' => 8]]); + } finally { + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'paid_committed', + ]); + $this->assertSame('pending', $service->fresh()->status); + } + } + + public function test_cancellation_tombstone_wins_after_external_create(): void + { + $service = $this->makeService(); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed', + provisioningStartedAt: now(), + provisioningLeaseId: 'lease', + cancellationRequestedAt: now() + ); + $this->insertAllocation($reservationId); + + $this->assertFalse( + $this->service()->completeProvisioning( + $service, + 'lease', + $this->externalServer() + ) + ); + + $this->assertSame('cancellation_pending', $service->fresh()->status); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'paid_committed', + 'external_server_id' => 71, + ]); + } + + public function test_unpaid_cancellation_returns_product_stock_exactly_once(): void + { + [$service, $product] = $this->makeStockedService(stock: 4); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id + ); + $this->insertAllocation($reservationId); + + $this->assertTrue($this->service()->requestServiceCancellation($service)); + $this->assertSame(5, $product->fresh()->stock); + $this->assertTrue( + app(DurableFulfillmentService::class) + ->cancellationIsDurablyComplete($service) + ); + $this->assertNotNull( + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('product_stock_released_at') + ); + + $this->assertFalse($this->service()->requestServiceCancellation($service)); + $this->assertSame(5, $product->fresh()->stock); + } + + public function test_paid_cancellation_returns_stock_only_after_external_absence(): void + { + [$service, $product] = $this->makeStockedService( + stock: 4, + status: Service::STATUS_ACTIVE + ); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'confirmed', + consumedAt: now() + ); + + $this->assertTrue($this->service()->requestServiceCancellation($service)); + $this->assertSame(4, $product->fresh()->stock); + $this->assertFalse( + app(DurableFulfillmentService::class) + ->cancellationIsDurablyComplete($service) + ); + $this->assertNull( + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('product_stock_released_at') + ); + + $this->assertTrue($this->service()->completeServiceCancellation($service)); + $this->assertTrue($this->service()->completeServiceCancellation($service)); + $this->assertSame(5, $product->fresh()->stock); + $this->assertTrue( + app(DurableFulfillmentService::class) + ->cancellationIsDurablyComplete($service) + ); + } + + public function test_failed_external_cancellation_keeps_product_stock_committed(): void + { + [$service, $product] = $this->makeStockedService( + stock: 4, + status: Service::STATUS_ACTIVE + ); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'confirmed', + consumedAt: now() + ); + $this->service()->requestServiceCancellation($service); + + $this->service()->recordPermanentCancellationFailure( + $service, + new \RuntimeException('Pterodactyl delete failed') + ); + + $this->assertSame(4, $product->fresh()->stock); + $this->assertNull( + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('product_stock_released_at') + ); + } + + public function test_invoice_cancellation_atomically_releases_checkout_obligations(): void + { + [$service, $product] = $this->makeStockedService(4); + $invoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PENDING, + 'currency_code' => 'USD', + ]); + $invoice->items()->create([ + 'reference_type' => Service::class, + 'reference_id' => $service->id, + 'price' => 12.50, + 'quantity' => 1, + 'description' => 'Dynamic server', + ]); + $reservationId = $this->insertReservation( + serviceId: $service->id, + invoiceId: $invoice->id, + userId: $service->user_id + ); + $this->insertAllocation($reservationId); + + app(CancelInvoiceService::class)->handle($invoice); + + $this->assertSame(Invoice::STATUS_CANCELLED, $invoice->fresh()->status); + $this->assertSame(Service::STATUS_CANCELLED, $service->fresh()->status); + $this->assertSame(5, $product->fresh()->stock); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'cancelled', + ]); + $this->assertNotNull( + DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservationId) + ->value('released_at') + ); + } + + public function test_capacity_invoice_cannot_be_raw_cancelled_or_deleted(): void + { + $service = $this->makeService(); + $invoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PENDING, + ]); + $this->insertReservation( + serviceId: $service->id, + invoiceId: $invoice->id, + userId: $service->user_id + ); + + try { + $invoice->update(['status' => Invoice::STATUS_CANCELLED]); + $this->fail('Expected raw capacity invoice cancellation to fail.'); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'fulfillment coordinator', + $exception->getMessage() + ); + } + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('cannot be deleted'); + $invoice->delete(); + } + + public function test_active_allocation_cannot_be_claimed_twice(): void + { + $first = $this->insertReservation(); + $second = $this->insertReservation(); + $this->insertAllocation($first, allocationId: 7001); + + $this->expectException(QueryException::class); + $this->insertAllocation($second, allocationId: 7001); + } + + public function test_dynamic_service_status_cannot_bypass_fulfillment_state_machine(): void + { + $service = $this->makeService(); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed' + ); + $service->status = 'active'; + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('fulfillment state machine'); + + $service->save(); + } + + public function test_reservation_identity_guard_survives_mutable_product_classification(): void + { + $service = $this->makeService(); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id + ); + + $service->currency_code = 'AUD'; + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Reservation-backed service identity'); + + $service->save(); + } + + public function test_reserved_panel_host_cannot_change_while_commitment_is_live(): void + { + $server = Server::query()->create([ + 'name' => 'Reserved Pterodactyl', + 'extension' => 'Pterodactyl', + 'type' => 'server', + 'enabled' => true, + ]); + $host = $server->settings()->create([ + 'key' => 'host', + 'value' => 'https://panel.example.com', + 'type' => 'string', + 'encrypted' => false, + ]); + $reservationId = $this->insertReservation(); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update(['server_extension_id' => $server->id]); + + $host->value = 'https://different-panel.example.com'; + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('pinned by active capacity commitments'); - $this->configurationService->shouldReceive('assertServiceMatches') - ->once() - ->with($service, Mockery::on(fn ($row) => (int) $row->id === $reservationId)); + $host->save(); + } - $context = $this->service()->beginProvisioning($service); + public function test_exclusive_provisioning_control_cannot_change_while_commitment_is_live(): void + { + $extension = Extension::query()->firstOrCreate( + [ + 'extension' => ExtensionLifecycleGuard::DYNAMIC_PTERODACTYL, + 'type' => 'other', + ], + [ + 'name' => 'Dynamic Pterodactyl', + 'enabled' => true, + ] + ); + $control = $extension->settings()->firstOrCreate( + ['key' => 'exclusive_provisioning_control'], + [ + 'value' => true, + 'type' => 'boolean', + 'encrypted' => false, + ] + ); + if (! (bool) $control->value) { + $control->value = true; + $control->save(); + } + $this->insertReservation(); - $this->assertSame(4, $context['node_id']); - $this->assertFalse($context['already_consumed']); - $this->assertDatabaseHas('ptero_resource_reservations', [ - 'id' => $reservationId, - 'status' => 'pending', - ]); - $this->assertNotNull( - DB::table('ptero_resource_reservations')->where('id', $reservationId)->value('provisioning_started_at') + $control->value = false; + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('cannot be disabled, replaced, or uninstalled'); + + $control->save(); + } + + public function test_stock_control_setting_cannot_be_deleted_while_commitment_is_live(): void + { + $extension = Extension::query()->firstOrCreate( + [ + 'extension' => ExtensionLifecycleGuard::DYNAMIC_PTERODACTYL, + 'type' => 'other', + ], + [ + 'name' => 'Dynamic Pterodactyl', + 'enabled' => true, + ] + ); + $control = $extension->settings()->firstOrCreate( + ['key' => 'exclusive_provisioning_control'], + [ + 'value' => true, + 'type' => 'boolean', + 'encrypted' => false, + ] ); + $this->insertReservation(); - $this->assertNotNull($context['provisioning_lease_id']); - $this->assertTrue( - $this->service()->completeProvisioning( - $service->id, - $context['provisioning_lease_id'] - ) + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('cannot be disabled, replaced, or uninstalled'); + + $control->delete(); + } + + public function test_resource_property_create_update_and_delete_bypasses_are_blocked(): void + { + $service = $this->makeService(); + $update = $service->properties()->create([ + 'key' => 'memory', + 'value' => 4096, + ]); + $delete = $service->properties()->create([ + 'key' => 'disk', + 'value' => 51200, + ]); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id ); - $this->assertDatabaseHas('ptero_resource_reservations', [ - 'id' => $reservationId, - 'status' => 'confirmed', + + $operations = [ + fn () => $service->properties()->create([ + 'key' => 'cpu', + 'value' => 300, + ]), + function () use ($update): void { + $update->value = 8192; + $update->save(); + }, + fn () => $delete->delete(), + ]; + foreach ($operations as $operation) { + try { + $operation(); + $this->fail('Expected resource property mutation to be blocked.'); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'capacity-aware fulfillment coordinator', + $exception->getMessage() + ); + } + } + } + + public function test_resource_config_create_update_and_delete_bypasses_are_blocked(): void + { + $service = $this->makeService(); + $memory = $this->resourceOption('Memory', 'memory'); + $cpu = $this->resourceOption('CPU', 'cpu'); + $disk = $this->resourceOption('Disk', 'disk'); + $update = $service->configs()->create([ + 'config_option_id' => $memory->id, + 'config_value_id' => null, + 'slider_value' => 4096, ]); - $this->assertNotNull( - DB::table('ptero_resource_reservations')->where('id', $reservationId)->value('consumed_at') + $delete = $service->configs()->create([ + 'config_option_id' => $disk->id, + 'config_value_id' => null, + 'slider_value' => 51200, + ]); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id + ); + + $operations = [ + fn () => $service->configs()->create([ + 'config_option_id' => $cpu->id, + 'config_value_id' => null, + 'slider_value' => 300, + ]), + function () use ($update): void { + $update->slider_value = 8192; + $update->save(); + }, + fn () => $delete->delete(), + ]; + foreach ($operations as $operation) { + try { + $operation(); + $this->fail('Expected resource config mutation to be blocked.'); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'capacity-aware fulfillment coordinator', + $exception->getMessage() + ); + } + } + + FulfillmentStatusTransitionService::run( + $service, + function () use ($update): void { + $update->slider_value = 8192; + $update->save(); + } ); + $this->assertSame(8192.0, (float) $update->fresh()->slider_value); } - public function test_active_provisioning_lease_rejects_a_second_worker(): void + public function test_reservation_backed_service_cannot_be_hard_deleted(): void { $service = $this->makeService(); $this->insertReservation( serviceId: $service->id, userId: $service->user_id, - provisioningStartedAt: now() + status: 'confirmed' ); - $this->configurationService->shouldNotReceive('assertServiceMatches'); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('already being provisioned'); + $this->expectExceptionMessage('retained as fulfillment records'); - $this->service()->beginProvisioning($service); + $service->delete(); } - public function test_failed_provisioning_releases_only_the_attempt_lease(): void + public function test_exact_guarantee_boundary_expires_order_and_blocks_payment(): void + { + Carbon::setTestNow('2026-07-26 12:00:00'); + + try { + $service = $this->makeService(); + $invoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PENDING, + 'due_at' => now(), + ]); + $invoice->items()->create([ + 'reference_type' => Service::class, + 'reference_id' => $service->id, + 'price' => 10, + 'quantity' => 1, + 'description' => 'Dynamic server', + ]); + $reservationId = $this->insertReservation( + serviceId: $service->id, + invoiceId: $invoice->id, + userId: $service->user_id, + guaranteedUntil: now() + ); + $this->insertAllocation($reservationId); + + $this->assertSame(1, $this->service()->cleanupExpired()); + $this->assertSame(Invoice::STATUS_CANCELLED, $invoice->fresh()->status); + $this->assertSame(Service::STATUS_CANCELLED, $service->fresh()->status); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'expired', + ]); + $this->assertNotNull( + DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservationId) + ->value('released_at') + ); + try { + app(MarkInvoicePaidService::class)->handle($invoice); + $this->fail('Expected the cancelled day-eight invoice to reject payment.'); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'capacity guarantee deadline expired', + $exception->getMessage() + ); + } + } finally { + Carbon::setTestNow(); + } + } + + public function test_late_gateway_payment_is_preserved_for_refund_review(): void + { + Carbon::setTestNow('2026-07-26 12:00:01'); + + try { + $service = $this->makeService(); + $invoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PENDING, + 'due_at' => now()->subSecond(), + 'currency_code' => 'USD', + ]); + $invoice->items()->create([ + 'reference_type' => Service::class, + 'reference_id' => $service->id, + 'price' => 12.50, + 'quantity' => 1, + 'description' => 'Dynamic server', + ]); + $reservationId = $this->insertReservation( + serviceId: $service->id, + invoiceId: $invoice->id, + userId: $service->user_id, + guaranteedUntil: now()->subSecond() + ); + + ExtensionHelper::addPayment( + $invoice->id, + null, + 12.50, + transactionId: 'late-gateway-transaction' + ); + + $this->assertSame(1, $invoice->transactions()->count()); + $this->assertSame(Invoice::STATUS_PENDING, $invoice->fresh()->status); + $this->assertNotNull( + $invoice->fresh()->payment_attention_required_at + ); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'pending', + ]); + } finally { + Carbon::setTestNow(); + } + } + + public function test_partial_payment_expiry_releases_capacity_without_cancelling_payment_fact(): void + { + Carbon::setTestNow('2026-07-26 12:00:00'); + + try { + $service = $this->makeService(); + $invoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PENDING, + 'due_at' => now()->addDays(7), + 'currency_code' => 'USD', + ]); + $invoice->items()->create([ + 'reference_type' => Service::class, + 'reference_id' => $service->id, + 'price' => 12.50, + 'quantity' => 1, + 'description' => 'Dynamic server', + ]); + $reservationId = $this->insertReservation( + serviceId: $service->id, + invoiceId: $invoice->id, + userId: $service->user_id, + guaranteedUntil: now()->addDays(7) + ); + $this->insertAllocation($reservationId); + ExtensionHelper::addPayment( + $invoice->id, + null, + 5.00, + transactionId: 'partial-gateway-transaction' + ); + + Carbon::setTestNow(now()->addDays(7)); + $this->assertSame(1, $this->service()->cleanupExpired()); + + $this->assertSame(1, $invoice->transactions()->count()); + $this->assertSame(Invoice::STATUS_PENDING, $invoice->fresh()->status); + $this->assertNotNull( + $invoice->fresh()->payment_attention_required_at + ); + $this->assertSame( + Service::STATUS_PROVISIONING_FAILED, + $service->fresh()->status + ); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'expired', + ]); + } finally { + Carbon::setTestNow(); + } + } + + public function test_mixed_invoice_expiry_releases_dynamic_and_static_stock_once(): void + { + Carbon::setTestNow('2026-07-26 12:00:00'); + + try { + [$dynamicService, $dynamicProduct] = $this->makeStockedService(4); + [$staticService, $staticProduct] = $this->makeStockedService( + 7, + userId: $dynamicService->user_id + ); + $invoice = Invoice::factory()->create([ + 'user_id' => $dynamicService->user_id, + 'status' => Invoice::STATUS_PENDING, + 'due_at' => now(), + 'currency_code' => 'USD', + ]); + foreach ([$dynamicService, $staticService] as $linkedService) { + $invoice->items()->create([ + 'reference_type' => Service::class, + 'reference_id' => $linkedService->id, + 'price' => 12.50, + 'quantity' => 1, + 'description' => 'Server', + ]); + } + $reservationId = $this->insertReservation( + serviceId: $dynamicService->id, + invoiceId: $invoice->id, + userId: $dynamicService->user_id, + guaranteedUntil: now() + ); + $this->insertAllocation($reservationId); + + $this->assertSame(1, $this->service()->cleanupExpired()); + $this->assertSame(0, $this->service()->cleanupExpired()); + + $this->assertSame(5, $dynamicProduct->fresh()->stock); + $this->assertSame(8, $staticProduct->fresh()->stock); + $this->assertSame( + Service::STATUS_CANCELLED, + $dynamicService->fresh()->status + ); + $this->assertSame( + Service::STATUS_CANCELLED, + $staticService->fresh()->status + ); + $this->assertSame( + Invoice::STATUS_CANCELLED, + $invoice->fresh()->status + ); + } finally { + Carbon::setTestNow(); + } + } + + public function test_mixed_invoice_payment_attention_releases_all_stock_once(): void + { + Carbon::setTestNow('2026-07-26 12:00:00'); + + try { + [$dynamicService, $dynamicProduct] = $this->makeStockedService(4); + [$staticService, $staticProduct] = $this->makeStockedService( + 7, + userId: $dynamicService->user_id + ); + $invoice = Invoice::factory()->create([ + 'user_id' => $dynamicService->user_id, + 'status' => Invoice::STATUS_PENDING, + 'due_at' => now()->addDays(7), + 'currency_code' => 'USD', + ]); + foreach ([$dynamicService, $staticService] as $linkedService) { + $invoice->items()->create([ + 'reference_type' => Service::class, + 'reference_id' => $linkedService->id, + 'price' => 12.50, + 'quantity' => 1, + 'description' => 'Server', + ]); + } + $reservationId = $this->insertReservation( + serviceId: $dynamicService->id, + invoiceId: $invoice->id, + userId: $dynamicService->user_id, + guaranteedUntil: now()->addDays(7) + ); + $this->insertAllocation($reservationId); + ExtensionHelper::addPayment( + $invoice->id, + null, + 5, + transactionId: 'mixed-partial-payment' + ); + + Carbon::setTestNow(now()->addDays(7)); + $this->assertSame(1, $this->service()->cleanupExpired()); + $this->assertSame(0, $this->service()->cleanupExpired()); + + $this->assertSame(5, $dynamicProduct->fresh()->stock); + $this->assertSame(8, $staticProduct->fresh()->stock); + $this->assertSame( + Service::STATUS_PROVISIONING_FAILED, + $dynamicService->fresh()->status + ); + $this->assertSame( + Service::STATUS_PROVISIONING_FAILED, + $staticService->fresh()->status + ); + $this->assertSame( + Invoice::STATUS_PENDING, + $invoice->fresh()->status + ); + $this->assertNotNull( + $invoice->fresh()->payment_attention_required_at + ); + } finally { + Carbon::setTestNow(); + } + } + + public function test_generic_order_age_cron_cannot_shorten_seven_day_capacity_guarantee(): void + { + Carbon::setTestNow('2026-07-26 12:00:00'); + + try { + config(['settings.cronjob_order_cancel' => 3]); + $service = $this->makeService(); + DB::table('services') + ->where('id', $service->id) + ->update(['created_at' => now()->subDays(4)]); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + guaranteedUntil: now()->addDays(3) + ); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update(['expires_at' => now()->addDays(3)]); + $this->insertAllocation($reservationId); + + $this->artisan('app:cron-job')->assertExitCode(0); + $this->assertSame(Service::STATUS_PENDING, $service->fresh()->status); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'pending', + ]); + + Carbon::setTestNow(now()->addDays(3)); + $this->assertSame(1, $this->service()->cleanupExpired()); + $this->assertSame(Service::STATUS_CANCELLED, $service->fresh()->status); + } finally { + Carbon::setTestNow(); + } + } + + public function test_checkout_cleanup_never_reclaims_upgrade_reservations(): void { $service = $this->makeService(); $reservationId = $this->insertReservation( serviceId: $service->id, userId: $service->user_id, - provisioningStartedAt: now(), - provisioningLeaseId: 'active-lease' + guaranteedUntil: now()->subSecond() ); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'purpose' => 'upgrade', + 'expires_at' => now()->subSecond(), + ]); + $this->insertAllocation($reservationId); - $this->service()->failProvisioning( - $service->id, - 'active-lease', - new \RuntimeException('Pterodactyl unavailable') + $this->assertSame(0, $this->service()->cleanupExpired()); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'purpose' => 'upgrade', + 'status' => ResourceReservation::STATUS_PENDING, + ]); + $this->assertDatabaseHas('ptero_reservation_allocations', [ + 'reservation_id' => $reservationId, + 'released_at' => null, + ]); + } + + public function test_cron_can_suspend_a_confirmed_dynamic_service_through_coordinator(): void + { + Queue::fake(); + config([ + 'settings.cronjob_order_suspend' => 2, + 'settings.cronjob_invoice' => 7, + ]); + $service = $this->makeService(status: Service::STATUS_ACTIVE); + DB::table('services')->where('id', $service->id)->update([ + 'expires_at' => now()->subDays(3), + 'price' => 10, + ]); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'confirmed' ); - $reservation = DB::table('ptero_resource_reservations')->where('id', $reservationId)->first(); - $this->assertSame('pending', $reservation->status); - $this->assertNull($reservation->provisioning_started_at); - $this->assertSame('Pterodactyl unavailable', $reservation->last_provisioning_error); + $this->artisan('app:cron-job')->assertExitCode(0); + + $this->assertSame(Service::STATUS_SUSPENDED, $service->fresh()->status); + Queue::assertPushed( + SuspendJob::class, + fn (SuspendJob $job): bool => (int) $job->service->id === (int) $service->id + ); } - public function test_stale_worker_cannot_consume_or_clear_a_newer_lease(): void + public function test_paid_renewal_can_reactivate_confirmed_dynamic_service(): void + { + Queue::fake(); + $service = $this->makeService(status: Service::STATUS_SUSPENDED); + $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'confirmed' + ); + + app(RenewServiceService::class)->handle($service); + + $this->assertSame(Service::STATUS_ACTIVE, $service->fresh()->status); + } + + public function test_mixed_paid_invoice_routes_only_the_row_backed_service_through_dynamic_commit(): void + { + Bus::fake([CreateJob::class]); + $server = Server::query()->create([ + 'name' => 'Pterodactyl', + 'extension' => 'Pterodactyl', + 'type' => 'server', + 'enabled' => true, + ]); + $dynamicProduct = Product::factory()->create(['server_id' => $server->id]); + $staticProduct = Product::factory()->create(['server_id' => $server->id]); + $dynamicPlan = $dynamicProduct->plans()->create([ + 'name' => 'Dynamic', + 'type' => 'recurring', + 'billing_period' => 1, + 'billing_unit' => 'month', + ]); + $staticPlan = $staticProduct->plans()->create([ + 'name' => 'Static', + 'type' => 'recurring', + 'billing_period' => 1, + 'billing_unit' => 'month', + ]); + $user = User::withoutEvents(fn () => User::factory()->create()); + $dynamicService = Service::withoutEvents(fn () => Service::factory()->create([ + 'user_id' => $user->id, + 'product_id' => $dynamicProduct->id, + 'plan_id' => $dynamicPlan->id, + 'status' => Service::STATUS_PENDING, + 'currency_code' => 'USD', + ])); + $staticService = Service::withoutEvents(fn () => Service::factory()->create([ + 'user_id' => $user->id, + 'product_id' => $staticProduct->id, + 'plan_id' => $staticPlan->id, + 'status' => Service::STATUS_PENDING, + 'currency_code' => 'USD', + ])); + $invoice = Invoice::factory()->create([ + 'user_id' => $user->id, + 'status' => Invoice::STATUS_PENDING, + 'currency_code' => 'USD', + ]); + foreach ([$dynamicService, $staticService] as $invoiceService) { + $invoice->items()->create([ + 'reference_type' => Service::class, + 'reference_id' => $invoiceService->id, + 'price' => 12.50, + 'quantity' => 1, + 'description' => 'Mixed checkout service', + ]); + } + $this->insertReservation( + serviceId: $dynamicService->id, + invoiceId: $invoice->id, + userId: $user->id, + guaranteedUntil: now()->addDays(7) + ); + + $reservationService = Mockery::mock(ReservationService::class); + $reservationService->shouldReceive('commitPaidService') + ->once() + ->withArgs( + fn (Service $candidate, Invoice $paidInvoice): bool => + $candidate->is($dynamicService) && $paidInvoice->is($invoice) + ) + ->andReturnTrue(); + $this->app->instance(ReservationService::class, $reservationService); + + $fulfillment = app(DurableFulfillmentService::class); + $this->assertTrue($fulfillment->isReservationBacked($dynamicService)); + $this->assertFalse($fulfillment->isReservationBacked($staticService)); + + app(RenewServiceService::class)->handle($dynamicService, $invoice); + app(RenewServiceService::class)->handle($staticService, $invoice); + + $this->assertCount(2, Bus::dispatched(CreateJob::class)); + Bus::assertDispatched( + CreateJob::class, + fn (CreateJob $job): bool => $job->service->is($dynamicService) + ); + Bus::assertDispatched( + CreateJob::class, + fn (CreateJob $job): bool => $job->service->is($staticService) + ); + $this->assertSame(Service::STATUS_ACTIVE, $staticService->fresh()->status); + } + + public function test_missing_extension_runtime_cannot_fall_back_to_legacy_paid_provisioning(): void { + Bus::fake([CreateJob::class]); $service = $this->makeService(); + $invoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PENDING, + 'currency_code' => 'USD', + ]); $reservationId = $this->insertReservation( serviceId: $service->id, + invoiceId: $invoice->id, userId: $service->user_id, - provisioningStartedAt: now(), - provisioningLeaseId: 'new-lease' + guaranteedUntil: now()->addDays(7) + ); + $missingRuntime = new class extends DurableFulfillmentService + { + protected function reservationService(): ?object + { + return null; + } + }; + $this->app->instance( + DurableFulfillmentService::class, + $missingRuntime ); try { - $this->service()->completeProvisioning($service->id, 'old-lease'); - $this->fail('Expected stale provisioning lease rejection.'); + app(RenewServiceService::class)->handle($service, $invoice); + $this->fail('Expected missing durable runtime to block provisioning.'); } catch (\RuntimeException $exception) { - $this->assertStringContainsString('no longer owns', $exception->getMessage()); + $this->assertStringContainsString( + 'durable fulfillment extension is unavailable', + $exception->getMessage() + ); } - $this->service()->failProvisioning( - $service->id, - 'old-lease', - new \RuntimeException('stale worker failed') + Bus::assertNotDispatched(CreateJob::class); + $this->assertSame(Service::STATUS_PENDING, $service->fresh()->status); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => ResourceReservation::STATUS_PENDING, + ]); + } + + public function test_missing_extension_runtime_cannot_partially_cancel_or_release_stock(): void + { + [$service, $product] = $this->makeStockedService(4); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id ); + $missingRuntime = new class extends DurableFulfillmentService + { + protected function reservationService(): ?object + { + return null; + } + }; - $reservation = DB::table('ptero_resource_reservations')->where('id', $reservationId)->first(); - $this->assertSame('pending', $reservation->status); - $this->assertSame('new-lease', $reservation->provisioning_lease_id); - $this->assertNotNull($reservation->provisioning_started_at); - $this->assertNull($reservation->last_provisioning_error); + try { + $missingRuntime->requestCancellation($service); + $this->fail('Expected missing durable runtime to block cancellation.'); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'durable fulfillment extension is unavailable', + $exception->getMessage() + ); + } + + $this->assertSame(4, $product->fresh()->stock); + $this->assertSame(Service::STATUS_PENDING, $service->fresh()->status); + $this->assertNull($service->fresh()->product_stock_released_at); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => ResourceReservation::STATUS_PENDING, + 'product_stock_released_at' => null, + ]); } - public function test_completed_reservation_is_idempotent_for_server_reconciliation(): void + public function test_allocation_row_drift_is_rejected_before_external_provisioning(): void { $service = $this->makeService(); - $this->insertReservation( + $reservationId = $this->insertReservation( serviceId: $service->id, userId: $service->user_id, - status: 'confirmed', - consumedAt: now() + status: 'paid_committed' ); + $this->insertAllocation($reservationId); + DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservationId) + ->update(['port' => 25566]); - $context = $this->service()->beginProvisioning($service); + $this->configurationService->shouldNotReceive('assertServiceMatches'); + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Allocation claims no longer match'); - $this->assertTrue($context['already_consumed']); - $this->assertTrue($this->service()->completeProvisioning($service->id)); + $this->service()->beginProvisioning($service); + } + + public function test_reconciler_recovers_a_stale_crashed_worker_lease(): void + { + Bus::fake([CreateJob::class]); + $service = $this->makeService(status: 'provisioning'); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed', + provisioningStartedAt: now()->subMinutes(6), + provisioningLeaseId: 'abandoned-lease' + ); + + $this->assertSame(1, $this->service()->reconcileStalledPaidCommitments()); + $reservation = DB::table('ptero_resource_reservations')->find($reservationId); + $this->assertNull($reservation->provisioning_started_at); + $this->assertNull($reservation->provisioning_lease_id); + $this->assertNotNull($reservation->next_provisioning_attempt_at); + Bus::assertDispatched( + CreateJob::class, + fn (CreateJob $job) => $job->service->is($service) + ); + } + + public function test_fixed_port_is_claimed_before_an_earlier_wildcard_mapping(): void + { + $service = $this->service(); + $reflection = new \ReflectionClass($service); + $method = $reflection->getMethod('mapAllocationRequirements'); + $method->setAccessible(true); + + $mapped = $method->invoke($service, [ + ['id' => 7001, 'ip' => '192.0.2.10', 'port' => 27015], + ['id' => 7002, 'ip' => '192.0.2.10', 'port' => 25565], + ], [ + [ + 'environment_key' => 'SERVER_PORT', + 'requested_port' => null, + 'is_primary' => true, + ], + [ + 'environment_key' => 'QUERY_PORT', + 'requested_port' => 27015, + 'is_primary' => false, + ], + ]); + + $this->assertSame([ + [ + 'allocation_id' => 7001, + 'ip' => '192.0.2.10', + 'port' => 27015, + 'environment_key' => 'QUERY_PORT', + 'is_primary' => false, + ], + [ + 'allocation_id' => 7002, + 'ip' => '192.0.2.10', + 'port' => 25565, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ], + ], $mapped); } private function service(): ReservationService @@ -212,15 +2024,16 @@ private function service(): ReservationService return $service; } - private function makeService(): Service + private function makeService(string $status = 'pending'): Service { $user = User::withoutEvents(fn () => User::factory()->create()); $id = DB::table('services')->insertGetId([ 'user_id' => $user->id, - 'status' => 'pending', + 'status' => $status, 'currency_code' => 'USD', 'quantity' => 1, 'price' => '0.00', + 'expires_at' => now()->addMonth(), 'created_at' => now(), 'updated_at' => now(), ]); @@ -228,34 +2041,126 @@ private function makeService(): Service return Service::query()->findOrFail($id); } + /** + * @return array{Service, Product} + */ + private function makeStockedService( + int $stock, + string $status = Service::STATUS_PENDING, + ?int $userId = null + ): array { + $product = Product::factory()->create(['stock' => $stock]); + $service = $this->makeService($status); + DB::table('services') + ->where('id', $service->id) + ->update(array_filter([ + 'product_id' => $product->id, + 'user_id' => $userId, + ], fn ($value): bool => $value !== null)); + + return [$service->fresh(), $product]; + } + + private function resourceOption(string $name, string $resource): ConfigOption + { + return ConfigOption::create([ + 'name' => $name, + 'env_variable' => $resource, + 'type' => 'dynamic_slider', + 'hidden' => false, + 'upgradable' => true, + 'metadata' => [ + 'resource_type' => $resource, + 'min' => 1, + 'max' => 100000, + 'step' => 1, + 'default' => 1, + 'display_divisor' => 1, + 'pricing' => [ + 'model' => 'linear', + 'rate_per_unit' => 0, + ], + ], + ]); + } + + private function pterodactylProduct(): Product + { + $server = Server::query()->create([ + 'name' => 'Pterodactyl', + 'extension' => 'Pterodactyl', + 'type' => 'server', + 'enabled' => true, + ]); + + return Product::factory()->create(['server_id' => $server->id]); + } + private function insertReservation( ?int $serviceId = null, + ?int $invoiceId = null, ?int $cartId = null, ?int $cartItemGuardId = null, ?int $userId = null, string $status = 'pending', mixed $provisioningStartedAt = null, ?string $provisioningLeaseId = null, - mixed $consumedAt = null + mixed $consumedAt = null, + mixed $cancellationRequestedAt = null, + mixed $guaranteedUntil = null, + ?int $productId = null, + ?int $planId = null, + string $purpose = 'checkout', + ?int $upgradeGuardId = null ): int { + $payload = [ + 'customer_id' => $userId, + 'cart_id' => $cartId, + 'panel_identity' => str_repeat('c', 64), + 'node_id' => 4, + 'resources' => [ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 51200, + ], + 'provisioning_identity' => [ + 'nest_id' => 1, + 'egg_id' => 2, + 'user_external_id' => $userId !== null + ? "paymenter-user-{$userId}" + : null, + 'user_email' => $userId !== null + ? (string) User::query()->whereKey($userId)->value('email') + : null, + ], + 'allocations' => [[ + 'allocation_id' => 7001, + 'ip' => '192.0.2.10', + 'port' => 25565, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ]], + ]; + return DB::table('ptero_resource_reservations')->insertGetId([ - 'token' => str_repeat((string) random_int(1, 9), 64), + 'token' => Str::random(64), + 'purpose' => $purpose, 'cart_item_id' => null, 'cart_item_guard_id' => $cartItemGuardId, 'cart_id' => $cartId, 'server_extension_id' => null, - 'panel_identity' => null, + 'panel_identity' => str_repeat('c', 64), 'service_id' => $serviceId, + 'service_guard_id' => $serviceId, + 'upgrade_guard_id' => $upgradeGuardId, + 'invoice_id' => $invoiceId, 'user_id' => $userId, - 'product_id' => null, - 'plan_id' => null, + 'product_id' => $productId, + 'plan_id' => $planId, 'quantity' => 1, 'currency_code' => 'USD', - 'configuration_fingerprint' => str_repeat('a', 64), - 'configuration_payload' => json_encode([ - 'customer_id' => $userId, - 'cart_id' => $cartId, - ]), + 'configuration_fingerprint' => $this->configurationService->fingerprint($payload), + 'configuration_payload' => json_encode($payload), 'pricing_version' => str_repeat('b', 64), 'formula_version' => ReservationConfigurationService::FORMULA_VERSION, 'node_id' => 4, @@ -267,11 +2172,44 @@ private function insertReservation( 'pricing_breakdown' => json_encode([]), 'status' => $status, 'expires_at' => now()->addDay(), + 'guaranteed_until' => $guaranteedUntil ?? now()->addDay(), 'provisioning_started_at' => $provisioningStartedAt, 'provisioning_lease_id' => $provisioningLeaseId, + 'cancellation_requested_at' => $cancellationRequestedAt, 'consumed_at' => $consumedAt, 'created_at' => now(), 'updated_at' => now(), ]); } + + private function insertAllocation(int $reservationId, int $allocationId = 7001): void + { + DB::table('ptero_reservation_allocations')->insert([ + 'reservation_id' => $reservationId, + 'panel_identity' => str_repeat('c', 64), + 'node_id' => 4, + 'allocation_id' => $allocationId, + 'ip' => '192.0.2.10', + 'port' => 25565, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + + /** + * @return array + */ + private function externalServer(): array + { + return [ + 'attributes' => [ + 'id' => 71, + 'uuid' => '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', + 'identifier' => 'created', + 'user' => 44, + ], + ]; + } } diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index 86b062f..759244d 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -3,9 +3,10 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; use Illuminate\Foundation\Testing\DatabaseTransactions; -use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Http; +use Mockery; +use Paymenter\Extensions\Others\DynamicPterodactyl\Models\NodeCapacityPolicy; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\PterodactylInventoryService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceCalculationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; @@ -13,1016 +14,905 @@ class ResourceCalculationServiceTest extends LaravelTestCase { use DatabaseTransactions; - private ResourceCalculationService $service; + private const PANEL_IDENTITY = '7c6e2c72d2dd80adbf79bdce3fd8931102831742545776c0df049b9e2daef06f'; - protected function setUp(): void + public function test_cpu_policy_mutation_uses_scope_lock_and_rejects_live_commitment(): void { - parent::setUp(); - - Config::set('settings.debug', false); - Http::preventStrayRequests(); - - $reflection = new \ReflectionClass(ResourceCalculationService::class); - $this->service = $reflection->newInstanceWithoutConstructor(); - - foreach (['apiUrl' => 'https://panel.example.com', 'apiKey' => 'test-api-key'] as $property => $value) { - $propertyReflection = $reflection->getProperty($property); - $propertyReflection->setAccessible(true); - $propertyReflection->setValue($this->service, $value); - } - } - - public function test_get_locations_returns_parsed_array(): void - { - Http::fake([ - 'panel.example.com/*' => Http::response([ - 'data' => [ - ['attributes' => ['id' => 1, 'short' => 'us', 'long' => 'US East']], - ], - 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], - ], 200), + $policy = $this->createCpuPolicy(); + $this->assertDatabaseHas('ptero_capacity_scopes', [ + 'panel_identity' => self::PANEL_IDENTITY, + 'location_id' => 1, ]); - - $result = $this->service->getLocations(); - - Http::assertSentCount(1); - $this->assertCount(1, $result); - $this->assertEquals(1, $result[0]['id']); - $this->assertEquals('us', $result[0]['short']); - } - - public function test_429_throws_runtime_exception_with_rate_limit_message(): void - { - Http::fake([ - 'panel.example.com/*' => Http::response([], 429), + $this->insertReservation('cpu-policy-hold', 'pending', [ + 'memory' => 1024, + 'cpu' => 100, + 'disk' => 10240, ]); try { - $this->service->getLocations(); - $this->fail('Expected RuntimeException for 429 response'); - } catch (\RuntimeException $e) { - $this->assertMatchesRegularExpression('/rate limit/i', $e->getMessage()); - } finally { - Http::assertSentCount(1); // 429 must NOT retry - } - } - - public function test_500_throws_sanitized_runtime_exception(): void - { - Http::fake([ - 'panel.example.com/*' => Http::response(['error' => 'panel down'], 500), - ]); - - try { - $this->service->getLocations(); - $this->fail('Expected RuntimeException for 500 response'); - } catch (\RuntimeException $e) { - $this->assertMatchesRegularExpression('/500/', $e->getMessage()); - $this->assertStringNotContainsString('panel down', $e->getMessage()); - } finally { - Http::assertSentCount(1); // 500 must NOT retry - } - } - - public function test_connection_exception_retries_and_throws(): void - { - $attempts = 0; - - Http::fake(function () use (&$attempts) { - $attempts++; - throw new \Illuminate\Http\Client\ConnectionException('timed out'); - }); - - $this->expectException(\RuntimeException::class); - - try { - $this->service->getLocations(); - } catch (\RuntimeException $e) { - $this->assertSame(2, $attempts); // retry(2) = 2 total attempts (1 original + 1 retry) - - throw $e; - } - } - - public function test_connection_failure_message_is_sanitized(): void - { - Http::fake(function () { - throw new \Illuminate\Http\Client\ConnectionException( - 'cURL error 7: Failed to connect to panel-internal-host:8080' + $policy->update(['cpu_capacity_percent' => 1600]); + $this->fail('A live capacity hold must serialize and block policy mutation.'); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'live capacity commitment', + $exception->getMessage() ); - }); - - try { - $this->service->getLocations(); - $this->fail('Expected RuntimeException on connection failure'); - } catch (\RuntimeException $e) { - $this->assertStringContainsString('connection failed', $e->getMessage()); - $this->assertStringNotContainsString('panel-internal-host', $e->getMessage()); - $this->assertStringNotContainsString('8080', $e->getMessage()); - $this->assertStringNotContainsString('cURL', $e->getMessage()); } - } - - public function test_malformed_json_body_throws_runtime_exception(): void - { - Http::fake([ - 'panel.example.com/*' => Http::response('not json', 200), - ]); - try { - $this->service->getLocations(); - $this->fail('Expected RuntimeException for invalid JSON'); - } catch (\RuntimeException $e) { - $this->assertMatchesRegularExpression('/invalid JSON payload/i', $e->getMessage()); - } finally { - Http::assertSentCount(1); - } + $this->assertSame(800, $policy->fresh()->cpu_capacity_percent); } - public function test_get_node_location_throws_when_location_id_missing(): void + public function test_node_move_fails_closed_until_cpu_policy_identity_is_resynced(): void { - Http::fake([ - 'panel.example.com/*' => Http::response([ - 'attributes' => [ - 'id' => 5, - // location_id intentionally absent - ], - ], 200), - ]); - - $reflection = new \ReflectionClass($this->service); - $method = $reflection->getMethod('getNodeLocation'); - $method->setAccessible(true); + $this->createCpuPolicy(); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessageMatches('/missing location_id/'); - - $method->invoke($this->service, 5); - } + $node = $this->service( + node: $this->node(['location_id' => 2]) + )->getNodeAvailability(5); - public function test_get_location_availability_excludes_given_reservation_token(): void - { - $this->insertPendingReservation('token-a', 5, 1, ['memory' => 2048, 'cpu' => 100, 'disk' => 10240]); - $this->insertPendingReservation('token-b', 5, 1, ['memory' => 1024, 'cpu' => 50, 'disk' => 5120]); - - Http::fake($this->availabilityHttpFake(nodeId: 5, locationId: 1, totalMemory: 8192, totalDisk: 51200, totalCpuThreads: 4)); - - $result = $this->service->getLocationAvailability(1, 'token-a'); - - $this->assertSame(['memory' => 1024, 'cpu' => 50, 'disk' => 5120], $result['nodes'][0]['reserved']); - $this->assertSame(['memory' => 7168, 'cpu' => null, 'disk' => 46080], $result['nodes'][0]['available']); - $this->assertFalse($result['nodes'][0]['cpu_capacity_enforced']); - } - - public function test_verify_availability_with_self_exclusion_succeeds_on_edge_fit(): void - { - $resources = ['memory' => 4096, 'cpu' => 200, 'disk' => 10240]; - $this->insertPendingReservation('edge-fit', 5, 1, $resources); - - Http::fake($this->availabilityHttpFake(nodeId: 5, locationId: 1, totalMemory: 4096, totalDisk: 10240, totalCpuThreads: 2)); - - $this->assertTrue($this->service->verifyAvailability(5, $resources, 'edge-fit')); + $this->assertNotNull($node); + $this->assertFalse($node['eligible']); + $this->assertSame(0, $node['total']['cpu']); + $this->assertContains( + 'cpu_policy_identity_mismatch', + $node['ineligible_reasons'] + ); } - public function test_verify_availability_without_exclusion_fails_on_edge_fit(): void - { - $resources = ['memory' => 4096, 'cpu' => 200, 'disk' => 10240]; - $this->insertPendingReservation('edge-fit', 5, 1, $resources); + public function test_calculation_uses_conservative_maximum_across_node_and_server_snapshots(): void + { + $this->createCpuPolicy(capacity: 800, overcommit: 15000); + $service = $this->service( + node: $this->node([ + 'memory' => 1001, + 'disk' => 2001, + 'memory_overallocate' => 10, + 'disk_overallocate' => 50, + 'allocated_resources' => ['memory' => 1000, 'disk' => 200], + ]), + servers: [[ + 'id' => 81, + 'node' => 5, + // Node wins for memory; the newer server list wins for disk. + 'memory' => 999, + 'cpu' => 100, + 'disk' => 999, + ]] + ); - Http::fake($this->availabilityHttpFake(nodeId: 5, locationId: 1, totalMemory: 4096, totalDisk: 10240, totalCpuThreads: 2)); + $result = $service->getLocationAvailability(1); + $node = $result['nodes'][0]; - $this->assertFalse($this->service->verifyAvailability(5, $resources)); + $this->assertSame(['memory' => 1101, 'cpu' => 1200, 'disk' => 3001], $node['total']); + $this->assertSame(['memory' => 1000, 'cpu' => 100, 'disk' => 999], $node['allocated']); + $this->assertSame(['memory' => 101, 'cpu' => 1100, 'disk' => 2002], $node['available']); + $this->assertTrue($node['eligible']); + $this->assertTrue($node['cpu_capacity_enforced']); } - public function test_location_availability_groups_included_servers_by_node(): void + public function test_any_unbounded_existing_server_limit_makes_node_ineligible(): void { - Http::fake($this->availabilityHttpFake( - nodeId: 5, - locationId: 1, - totalMemory: 8192, - totalDisk: 51200, - totalCpuThreads: 4, - servers: [ - ['node' => 5, 'memory' => 1024, 'cpu' => 50, 'disk' => 5120], - ['node' => 6, 'memory' => 4096, 'cpu' => 200, 'disk' => 20480], - ], - additionalNodeIds: [6], - )); + $this->createCpuPolicy(); - $result = $this->service->getLocationAvailability(1); + foreach (['memory', 'cpu', 'disk'] as $unboundedResource) { + $server = [ + 'id' => 81, + 'node' => 5, + 'memory' => 1024, + 'cpu' => 100, + 'disk' => 10240, + ]; + $server[$unboundedResource] = 0; - Http::assertSentCount(1); - Http::assertSent(function ($request): bool { - $query = []; - parse_str(parse_url($request->url(), PHP_URL_QUERY) ?? '', $query); + $node = $this->service(servers: [$server]) + ->getLocationAvailability(1)['nodes'][0]; - return parse_url($request->url(), PHP_URL_PATH) === '/api/application/locations/1' - && ($query['include'] ?? null) === 'nodes,servers'; - }); - $this->assertSame(['memory' => 1024, 'cpu' => 50, 'disk' => 5120], $result['nodes'][0]['allocated']); - $this->assertSame(['memory' => 7168, 'cpu' => 350, 'disk' => 46080], $result['nodes'][0]['available']); - $this->assertSame(['memory' => 4096, 'cpu' => 200, 'disk' => 20480], $result['nodes'][1]['allocated']); - $this->assertSame(['memory' => 4096, 'cpu' => 200, 'disk' => 30720], $result['nodes'][1]['available']); + $this->assertFalse( + $node['eligible'], + "A zero {$unboundedResource} limit must fail the node closed." + ); + $this->assertContains('unlimited_existing_resource', $node['ineligible_reasons']); + } } - public function test_location_availability_rejects_malformed_included_relationships(): void + public function test_unbounded_node_overallocation_settings_fail_closed(): void { - Http::fake([ - 'panel.example.com/*' => Http::response([ - 'object' => 'location', - 'attributes' => [ - 'id' => 1, - 'relationships' => [ - 'nodes' => ['data' => 'not-an-array'], - 'servers' => ['data' => [['attributes' => 'not-an-array']]], - ], - ], - ], 200), - ]); + $this->createCpuPolicy(); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('invalid nodes relationship payload'); + foreach ([ + 'memory_overallocate' => 'unbounded_memory_overallocation', + 'disk_overallocate' => 'unbounded_disk_overallocation', + ] as $setting => $reason) { + $node = $this->service(node: $this->node([$setting => -1])) + ->getLocationAvailability(1)['nodes'][0]; - $this->service->getLocationAvailability(1); + $this->assertFalse( + $node['eligible'], + "A Pterodactyl {$setting} value of -1 must fail the node closed." + ); + $this->assertContains($reason, $node['ineligible_reasons']); + $this->assertSame( + $this->node()[$setting === 'memory_overallocate' ? 'memory' : 'disk'], + $node['total'][$setting === 'memory_overallocate' ? 'memory' : 'disk'] + ); + } } - public function test_location_availability_rejects_malformed_included_server_limits(): void - { - Http::fake([ - 'panel.example.com/*' => Http::response([ - 'object' => 'location', - 'attributes' => [ - 'id' => 1, - 'relationships' => [ - 'nodes' => ['data' => [[ - 'attributes' => [ - 'id' => 5, - 'location_id' => 1, - 'name' => 'Node 5', - 'fqdn' => 'node-5.example.com', - 'memory' => 8192, - 'disk' => 51200, - 'cpu_threads' => 4, - ], - ]]], - 'servers' => ['data' => [[ - 'attributes' => [ - 'node' => 5, - 'limits' => 'not-an-array', - ], - ]]], - ], - ], - ], 200), - ]); - - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('invalid included server payload'); - - $this->service->getLocationAvailability(1); + public function test_customer_allocation_claims_make_node_ineligible_even_without_headroom(): void + { + $this->createCpuPolicy(); + $node = $this->service(servers: [[ + 'id' => 81, + 'node' => 5, + 'memory' => 1024, + 'cpu' => 100, + 'disk' => 10240, + 'allocation_limit' => 2, + 'assigned_allocation_ids' => [501, 502], + 'allocation_headroom' => 0, + ]])->getLocationAvailability(1)['nodes'][0]; + + $this->assertFalse($node['eligible']); + $this->assertContains( + 'customer_allocation_headroom', + $node['ineligible_reasons'] + ); } - public function test_location_availability_rejects_incomplete_included_server_limits(): void + public function test_missing_cpu_policy_makes_node_ineligible_and_advertises_zero_cpu(): void { - Http::fake($this->availabilityHttpFake( - nodeId: 5, - locationId: 1, - totalMemory: 8192, - totalDisk: 51200, - totalCpuThreads: 4, - servers: [['node' => 5, 'memory' => 1024, 'cpu' => 50]], - )); + $node = $this->service()->getLocationAvailability(1)['nodes'][0]; - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('invalid included server payload'); - - $this->service->getLocationAvailability(1); + $this->assertFalse($node['eligible']); + $this->assertSame(0, $node['total']['cpu']); + $this->assertSame(0, $node['available']['cpu']); + $this->assertContains('cpu_policy_missing', $node['ineligible_reasons']); } - public function test_location_availability_rejects_negative_included_server_limits(): void + public function test_cpu_policy_cannot_change_during_a_live_commitment(): void { - Http::fake($this->availabilityHttpFake( - nodeId: 5, - locationId: 1, - totalMemory: 8192, - totalDisk: 51200, - totalCpuThreads: 4, - servers: [['node' => 5, 'memory' => 1024, 'cpu' => -1, 'disk' => 5120]], - )); + $policy = $this->createCpuPolicy(); + $this->insertReservation( + 'policy-hold', + 'pending', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240] + ); + $policy->cpu_overcommit_bps = 20000; $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('invalid included server payload'); + $this->expectExceptionMessage('live capacity commitment'); - $this->service->getLocationAvailability(1); + $policy->save(); } - public function test_location_availability_rejects_fractional_included_server_limits(): void + public function test_cpu_policy_cannot_be_deleted_during_a_live_commitment(): void { - Http::fake($this->availabilityHttpFake( - nodeId: 5, - locationId: 1, - totalMemory: 8192, - totalDisk: 51200, - totalCpuThreads: 4, - servers: [['node' => 5, 'memory' => 1024, 'cpu' => 50.5, 'disk' => 5120]], - )); + $policy = $this->createCpuPolicy(); + $this->insertReservation( + 'policy-delete-hold', + 'paid_committed', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240] + ); $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('invalid included server payload'); + $this->expectExceptionMessage('live capacity commitment'); - $this->service->getLocationAvailability(1); + $policy->delete(); } - public function test_location_availability_rejects_server_for_unknown_node(): void + public function test_private_maintenance_and_allocationless_nodes_are_excluded(): void { - Http::fake($this->availabilityHttpFake( - nodeId: 5, - locationId: 1, - totalMemory: 8192, - totalDisk: 51200, - totalCpuThreads: 4, - servers: [['node' => 6, 'memory' => 1024, 'cpu' => 50, 'disk' => 5120]], - )); - - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('unknown included node'); + $this->createCpuPolicy(); + $node = $this->service( + node: $this->node(['public' => false, 'maintenance_mode' => true]), + allocations: [] + )->getLocationAvailability(1)['nodes'][0]; - $this->service->getLocationAvailability(1); + $this->assertFalse($node['eligible']); + $this->assertSame([ + 'private_node', + 'maintenance_mode', + 'no_available_allocation', + ], $node['ineligible_reasons']); } - public function test_location_availability_rejects_duplicate_server_records(): void + public function test_pending_and_paid_committed_capacity_is_counted_with_self_exclusion(): void { - Http::fake($this->availabilityHttpFake( - nodeId: 5, - locationId: 1, - totalMemory: 8192, - totalDisk: 51200, - totalCpuThreads: 4, - servers: [ - ['id' => 501, 'node' => 5, 'memory' => 1024, 'cpu' => 50, 'disk' => 5120], - ['id' => 501, 'node' => 5, 'memory' => 1024, 'cpu' => 50, 'disk' => 5120], - ], - )); - - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('duplicate included server'); - - $this->service->getLocationAvailability(1); + $this->createCpuPolicy(); + $this->insertReservation('pending-self', 'pending', [ + 'memory' => 2048, + 'cpu' => 100, + 'disk' => 10240, + ]); + $this->insertReservation('paid-other', 'paid_committed', [ + 'memory' => 1024, + 'cpu' => 50, + 'disk' => 5120, + ], expiresAt: now()->subDay()); + + $node = $this->service() + ->getLocationAvailability(1, 'pending-self')['nodes'][0]; + + $this->assertSame( + ['memory' => 1024, 'cpu' => 50, 'disk' => 5120], + $node['reserved'] + ); } - public function test_location_availability_rejects_node_from_another_location(): void + public function test_upgrade_holds_count_only_positive_reserved_deltas(): void { - Http::fake($this->availabilityHttpFake( - nodeId: 5, - locationId: 1, - totalMemory: 8192, - totalDisk: 51200, - totalCpuThreads: 4, - includedNodeLocationId: 2, - )); + $this->createCpuPolicy(); + DB::table('ptero_resource_reservations')->insert([ + 'purpose' => 'upgrade', + 'token' => 'upgrade-delta', + 'panel_identity' => self::PANEL_IDENTITY, + 'node_id' => 5, + 'location_id' => 1, + // Target values must not be double-counted as newly reserved stock. + 'memory' => 8192, + 'cpu' => 400, + 'disk' => 51200, + 'reserved_memory' => 2048, + 'reserved_cpu' => 100, + 'reserved_disk' => 10240, + 'calculated_price' => 9.99, + 'pricing_breakdown' => json_encode([]), + 'status' => 'pending', + 'expires_at' => now()->addMinutes(15), + 'created_at' => now(), + 'updated_at' => now(), + ]); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('unexpected location'); + $node = $this->service()->getLocationAvailability(1)['nodes'][0]; - $this->service->getLocationAvailability(1); + $this->assertSame([ + 'memory' => 2048, + 'cpu' => 100, + 'disk' => 10240, + ], $node['reserved']); } - public function test_location_availability_rejects_node_without_cpu_threads(): void + public function test_confirmed_checkout_stays_overlaid_until_same_snapshot_proves_target(): void { - Http::fake([ - 'panel.example.com/*' => Http::response([ - 'attributes' => [ - 'relationships' => [ - 'nodes' => ['data' => [[ - 'attributes' => [ - 'id' => 5, - 'location_id' => 1, - 'name' => 'Node 5', - 'fqdn' => 'node-5.example.com', - 'memory' => 8192, - 'disk' => 51200, - ], - ]]], - 'servers' => ['data' => []], - ], - ], - ], 200), + $this->createCpuPolicy(); + $serviceRecord = \App\Models\Service::factory()->create(); + DB::table('services')->where('id', $serviceRecord->id)->update([ + 'status' => \App\Models\Service::STATUS_ACTIVE, ]); + $reservationId = $this->insertReservation( + 'confirmed-checkout-overlay', + 'confirmed', + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480] + ); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'purpose' => 'checkout', + 'service_id' => $serviceRecord->id, + 'external_server_id' => 81, + 'external_server_uuid' => + '10000000-0000-4000-8000-000000000081', + 'external_server_identifier' => 'server-81', + 'consumed_at' => now(), + ]); + + $stale = $this->service() + ->getLocationAvailability(1)['nodes'][0]; + $this->assertSame( + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480], + $stale['reserved'] + ); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('invalid included node payload'); - - $this->service->getLocationAvailability(1); + $reflected = $this->service(servers: [[ + 'id' => 81, + 'uuid' => '10000000-0000-4000-8000-000000000081', + 'identifier' => 'server-81', + 'external_id' => (string) $serviceRecord->id, + 'node' => 5, + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + ]])->getLocationAvailability(1)['nodes'][0]; + $this->assertSame( + ['memory' => 0, 'cpu' => 0, 'disk' => 0], + $reflected['reserved'] + ); } - public function test_location_availability_rejects_fractional_node_capacity(): void + public function test_confirmed_upgrade_supersedes_checkout_and_overlays_only_snapshot_deficit(): void { - Http::fake($this->availabilityHttpFake( - nodeId: 5, - locationId: 1, - totalMemory: 8192.5, - totalDisk: 51200, - totalCpuThreads: 4, - )); - - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('invalid included node payload'); - - $this->service->getLocationAvailability(1); - } + $this->createCpuPolicy(); + $serviceRecord = \App\Models\Service::factory()->create(); + DB::table('services')->where('id', $serviceRecord->id)->update([ + 'status' => \App\Models\Service::STATUS_ACTIVE, + ]); + $checkoutId = $this->insertReservation( + 'confirmed-checkout-before-upgrade', + 'confirmed', + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480] + ); + DB::table('ptero_resource_reservations') + ->where('id', $checkoutId) + ->update([ + 'purpose' => 'checkout', + 'service_id' => $serviceRecord->id, + 'external_server_id' => 81, + 'external_server_uuid' => + '10000000-0000-4000-8000-000000000081', + 'external_server_identifier' => 'server-81', + 'consumed_at' => now()->subHour(), + ]); + $upgradeId = $this->insertReservation( + 'confirmed-upgrade-target', + 'confirmed', + ['memory' => 8192, 'cpu' => 400, 'disk' => 40960] + ); + DB::table('ptero_resource_reservations') + ->where('id', $upgradeId) + ->update([ + 'purpose' => 'upgrade', + 'service_id' => $serviceRecord->id, + 'configuration_payload' => json_encode([ + 'external_server_id' => 81, + ]), + 'reserved_memory' => 4096, + 'reserved_cpu' => 200, + 'reserved_disk' => 20480, + 'consumed_at' => now(), + ]); + + $reflected = $this->service(servers: [[ + 'id' => 81, + 'uuid' => '10000000-0000-4000-8000-000000000081', + 'identifier' => 'server-81', + 'external_id' => (string) $serviceRecord->id, + 'node' => 5, + 'memory' => 8192, + 'cpu' => 400, + 'disk' => 40960, + ]])->getLocationAvailability(1)['nodes'][0]; + $this->assertSame( + ['memory' => 0, 'cpu' => 0, 'disk' => 0], + $reflected['reserved'], + 'The obsolete checkout vector must not remain overlaid.' + ); - public function test_snapshot_falls_back_when_included_servers_relationship_is_missing(): void - { - $calls = 0; - $node = $this->nodeWithServersPayload(1, 1, 'Node 1', []); - unset($node['attributes']['relationships']); - - Http::fake(function ($request) use (&$calls, $node) { - $calls++; - $url = $request->url(); - - if (str_contains($url, '/api/application/locations')) { - return Http::response([ - 'data' => [['attributes' => ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']]], - 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], - ], 200); - } - - if (str_contains($url, '/api/application/nodes')) { - return Http::response([ - 'data' => [$node], - 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], - ], 200); - } - - if (str_contains($url, '/api/application/servers')) { - return Http::response([ - 'data' => [[ - 'attributes' => [ - 'id' => 101, - 'node' => 1, - 'limits' => ['memory' => 1024, 'cpu' => 50, 'disk' => 5120], - ], - ]], - 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], - ], 200); - } - - return Http::response([], 404); - }); - - $snapshot = $this->service->buildClusterSnapshot(); - - $this->assertSame(['memory' => 1024, 'cpu' => 50, 'disk' => 5120], $snapshot['nodes'][1]['allocated']); - $this->assertSame(4, $calls); + $stale = $this->service(servers: [[ + 'id' => 81, + 'uuid' => '10000000-0000-4000-8000-000000000081', + 'identifier' => 'server-81', + 'external_id' => (string) $serviceRecord->id, + 'node' => 5, + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + ]])->getLocationAvailability(1)['nodes'][0]; + $this->assertSame( + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480], + $stale['reserved'] + ); } - public function test_snapshot_rejects_malformed_included_servers_relationship_without_fallback(): void + public function test_multiple_confirmed_upgrades_keep_only_latest_target(): void { - $calls = 0; - $node = $this->nodeWithServersPayload(1, 1, 'Node 1', []); - $node['attributes']['relationships']['servers']['data'] = 'not-an-array'; - - Http::fake($this->clusterSnapshotHttpFake( - $calls, - locations: [['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], - nodePages: [[$node]], - )); - - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('invalid servers relationship payload'); + $this->createCpuPolicy(); + $serviceRecord = \App\Models\Service::factory()->create(); + DB::table('services')->where('id', $serviceRecord->id)->update([ + 'status' => \App\Models\Service::STATUS_ACTIVE, + ]); - try { - $this->service->buildClusterSnapshot(); - } finally { - $this->assertSame(2, $calls); + foreach ([ + [ + 'token' => 'confirmed-base', + 'purpose' => 'checkout', + 'resources' => [4096, 200, 20480], + 'consumed_at' => now()->subHours(2), + ], + [ + 'token' => 'confirmed-upgrade-eight', + 'purpose' => 'upgrade', + 'resources' => [8192, 400, 40960], + 'consumed_at' => now()->subHour(), + ], + [ + 'token' => 'confirmed-upgrade-six', + 'purpose' => 'upgrade', + 'resources' => [6144, 300, 30720], + 'consumed_at' => now(), + ], + ] as $expectation) { + [$memory, $cpu, $disk] = $expectation['resources']; + $reservationId = $this->insertReservation( + $expectation['token'], + 'confirmed', + compact('memory', 'cpu', 'disk') + ); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'purpose' => $expectation['purpose'], + 'service_id' => $serviceRecord->id, + 'external_server_id' => + $expectation['purpose'] === 'checkout' ? 81 : null, + 'external_server_uuid' => + $expectation['purpose'] === 'checkout' + ? '10000000-0000-4000-8000-000000000081' + : null, + 'external_server_identifier' => + $expectation['purpose'] === 'checkout' + ? 'server-81' + : null, + 'configuration_payload' => json_encode([ + 'external_server_id' => 81, + ]), + 'consumed_at' => $expectation['consumed_at'], + ]); } - } - public function test_snapshot_rejects_malformed_included_servers_container_without_fallback(): void - { - $calls = 0; - $node = $this->nodeWithServersPayload(1, 1, 'Node 1', []); - $node['attributes']['relationships']['servers'] = 'not-an-array'; - - Http::fake($this->clusterSnapshotHttpFake( - $calls, - locations: [['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], - nodePages: [[$node]], - )); - - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('invalid servers relationship payload'); - - try { - $this->service->buildClusterSnapshot(); - } finally { - $this->assertSame(2, $calls); - } + $node = $this->service(servers: [[ + 'id' => 81, + 'uuid' => '10000000-0000-4000-8000-000000000081', + 'identifier' => 'server-81', + 'external_id' => (string) $serviceRecord->id, + 'node' => 5, + 'memory' => 6144, + 'cpu' => 300, + 'disk' => 30720, + ]])->getLocationAvailability(1)['nodes'][0]; + + $this->assertSame( + ['memory' => 0, 'cpu' => 0, 'disk' => 0], + $node['reserved'] + ); } - public function test_snapshot_with_single_location_single_node(): void + public function test_conflicting_confirmed_server_identities_fail_snapshot_proof_closed(): void { - $calls = 0; - - Http::fake($this->clusterSnapshotHttpFake( - $calls, - locations: [ - ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1'], - ], - nodePages: [[ - $this->nodeWithServersPayload(1, 1, 'Node 1', [ - ['memory' => 2048, 'cpu' => 100, 'disk' => 10240], + $this->createCpuPolicy(); + $serviceRecord = \App\Models\Service::factory()->create(); + DB::table('services')->where('id', $serviceRecord->id)->update([ + 'status' => \App\Models\Service::STATUS_ACTIVE, + ]); + $checkoutId = $this->insertReservation( + 'identity-checkout', + 'confirmed', + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480] + ); + DB::table('ptero_resource_reservations') + ->where('id', $checkoutId) + ->update([ + 'purpose' => 'checkout', + 'service_id' => $serviceRecord->id, + 'external_server_id' => 81, + 'consumed_at' => now()->subHour(), + ]); + $upgradeId = $this->insertReservation( + 'identity-upgrade', + 'confirmed', + ['memory' => 8192, 'cpu' => 400, 'disk' => 40960] + ); + DB::table('ptero_resource_reservations') + ->where('id', $upgradeId) + ->update([ + 'purpose' => 'upgrade', + 'service_id' => $serviceRecord->id, + 'configuration_payload' => json_encode([ + 'external_server_id' => 82, ]), - ]], - )); - - $snapshot = $this->service->buildClusterSnapshot(); - - $this->assertArrayNotHasKey('error', $snapshot); - $this->assertCount(1, $snapshot['locations']); - $this->assertSame([1], $snapshot['by_location'][1]['nodes']); - $this->assertSame(['memory' => 8192, 'cpu' => null, 'disk' => 51200], $snapshot['nodes'][1]['totals']); - $this->assertSame(['memory' => 2048, 'cpu' => 100, 'disk' => 10240], $snapshot['nodes'][1]['allocated']); - $this->assertSame(['memory' => 6144, 'cpu' => null, 'disk' => 40960], $snapshot['nodes'][1]['available']); - $this->assertSame(['memory' => 8192, 'cpu' => null, 'disk' => 51200], $snapshot['by_location'][1]['totals']); - $this->assertLessThanOrEqual(4, $calls); + 'consumed_at' => now(), + ]); + + $node = $this->service(servers: [[ + 'id' => 82, + 'uuid' => '10000000-0000-4000-8000-000000000082', + 'identifier' => 'server-82', + 'external_id' => (string) $serviceRecord->id, + 'node' => 5, + 'memory' => 8192, + 'cpu' => 400, + 'disk' => 40960, + ]])->getLocationAvailability(1)['nodes'][0]; + + $this->assertSame( + ['memory' => 8192, 'cpu' => 400, 'disk' => 40960], + $node['reserved'] + ); } - public function test_snapshot_aggregates_across_locations(): void + public function test_server_assignment_wins_over_stale_node_allocation_snapshot(): void { - $calls = 0; - - Http::fake($this->clusterSnapshotHttpFake( - $calls, - locations: [ - ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1'], - ['id' => 2, 'short' => 'dc2', 'long' => 'Data Center 2'], - ], - nodePages: [[ - $this->nodeWithServersPayload(1, 1, 'Node 1', [['memory' => 1024, 'cpu' => 50, 'disk' => 5120]]), - $this->nodeWithServersPayload(2, 1, 'Node 2', [['memory' => 2048, 'cpu' => 100, 'disk' => 10240]]), - $this->nodeWithServersPayload(3, 2, 'Node 3', [['memory' => 3072, 'cpu' => 150, 'disk' => 15360]]), - $this->nodeWithServersPayload(4, 2, 'Node 4', []), - $this->nodeWithServersPayload(5, 2, 'Node 5', [['memory' => 1024, 'cpu' => 50, 'disk' => 5120]]), + $this->createCpuPolicy(); + $node = $this->service( + servers: [[ + 'id' => 81, + 'node' => 5, + 'memory' => 1024, + 'cpu' => 100, + 'disk' => 10240, + 'assigned_allocation_ids' => [501], ]], - )); - - $snapshot = $this->service->buildClusterSnapshot(); - - $this->assertCount(5, $snapshot['nodes']); - $this->assertSame([1, 2], $snapshot['by_location'][1]['nodes']); - $this->assertSame([3, 4, 5], $snapshot['by_location'][2]['nodes']); - $this->assertSame(['memory' => 16384, 'cpu' => null, 'disk' => 102400], $snapshot['by_location'][1]['totals']); - $this->assertSame(['memory' => 3072, 'cpu' => 150, 'disk' => 15360], $snapshot['by_location'][1]['allocated']); - $this->assertSame(['memory' => 24576, 'cpu' => null, 'disk' => 153600], $snapshot['by_location'][2]['totals']); - $this->assertSame(['memory' => 4096, 'cpu' => 200, 'disk' => 20480], $snapshot['by_location'][2]['allocated']); - $this->assertLessThanOrEqual(4, $calls); - } - - public function test_snapshot_handles_paginated_location_response(): void - { - $calls = 0; - - Http::fake($this->clusterSnapshotHttpFake( - $calls, - locations: [ - [ - ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1'], - ['id' => 2, 'short' => 'dc2', 'long' => 'Data Center 2'], - ], - [ - ['id' => 3, 'short' => 'dc3', 'long' => 'Data Center 3'], - ], - ], - nodePages: [ - [ - $this->nodeWithServersPayload(1, 1, 'Node 1', []), - $this->nodeWithServersPayload(2, 2, 'Node 2', []), - $this->nodeWithServersPayload(3, 3, 'Node 3', []), - ], - ], - )); - - $snapshot = $this->service->buildClusterSnapshot(); - - $this->assertSame([1], $snapshot['by_location'][1]['nodes']); - $this->assertSame([2], $snapshot['by_location'][2]['nodes']); - $this->assertSame([3], $snapshot['by_location'][3]['nodes']); - $this->assertCount(3, $snapshot['nodes']); - $this->assertLessThanOrEqual(4, $calls); + allocations: [ + ['id' => 501, 'ip' => '192.0.2.5', 'port' => 25565], + ['id' => 502, 'ip' => '192.0.2.5', 'port' => 25566], + ['id' => 503, 'ip' => '192.0.2.6', 'port' => 25565], + ] + )->getLocationAvailability(1)['nodes'][0]; + + $this->assertSame( + [502, 503], + array_column($node['available_allocations'], 'id') + ); + $this->assertTrue($node['available_allocations'][0]['ip_in_use']); } - public function test_get_locations_rejects_non_advancing_pagination_metadata(): void + public function test_confirmed_local_claim_blocks_a_stale_free_allocation_snapshot(): void { - Http::fake([ - 'panel.example.com/*' => Http::response([ - 'data' => [], - 'meta' => [ - 'pagination' => [ - 'current_page' => 0, - 'count' => 0, - 'per_page' => 100, - 'total' => 0, - 'total_pages' => 1, - ], - ], - ], 200), + $this->createCpuPolicy(); + $serviceRecord = \App\Models\Service::factory()->create(); + DB::table('services')->where('id', $serviceRecord->id)->update([ + 'status' => \App\Models\Service::STATUS_ACTIVE, + ]); + $reservationId = $this->insertReservation( + 'confirmed-allocation-claim', + 'confirmed', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240] + ); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'service_id' => $serviceRecord->id, + 'external_server_id' => 81, + 'consumed_at' => now(), + ]); + DB::table('ptero_reservation_allocations')->insert([ + 'reservation_id' => $reservationId, + 'panel_identity' => self::PANEL_IDENTITY, + 'node_id' => 5, + 'allocation_id' => 501, + 'ip' => '192.0.2.5', + 'port' => 25565, + 'is_primary' => true, + 'released_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), ]); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('invalid pagination metadata'); + $node = $this->service(allocations: [ + ['id' => 501, 'ip' => '192.0.2.5', 'port' => 25565], + ['id' => 502, 'ip' => '192.0.2.6', 'port' => 25566], + ])->getLocationAvailability(1)['nodes'][0]; - $this->service->getLocations(); + $this->assertSame( + [502], + array_column($node['available_allocations'], 'id') + ); } - public function test_get_locations_rejects_missing_pagination_metadata(): void + public function test_locally_reserved_allocation_is_removed_from_panel_unassigned_inventory(): void { - Http::fake([ - 'panel.example.com/*' => Http::response(['data' => []], 200), + $this->createCpuPolicy(); + $reservationId = $this->insertReservation('allocation-hold', 'pending', [ + 'memory' => 1024, + 'cpu' => 100, + 'disk' => 10240, + ]); + DB::table('ptero_reservation_allocations')->insert([ + 'reservation_id' => $reservationId, + 'panel_identity' => self::PANEL_IDENTITY, + 'node_id' => 5, + 'allocation_id' => 502, + 'ip' => '192.0.2.5', + 'port' => 25566, + 'is_primary' => true, + 'created_at' => now(), + 'updated_at' => now(), ]); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('invalid pagination metadata'); - - $this->service->getLocations(); + $service = $this->service(allocations: [ + ['id' => 501, 'ip' => '192.0.2.5', 'port' => 25565], + ['id' => 502, 'ip' => '192.0.2.5', 'port' => 25566], + ]); + $node = $service->getLocationAvailability(1)['nodes'][0]; + + $this->assertSame([501], array_column($node['available_allocations'], 'id')); + $this->assertTrue($node['available_allocations'][0]['ip_in_use']); + $editedNode = $service + ->getLocationAvailability(1, 'allocation-hold')['nodes'][0]; + $this->assertSame( + [501, 502], + array_column($editedNode['available_allocations'], 'id') + ); + $this->assertSame( + [false, false], + array_column($editedNode['available_allocations'], 'ip_in_use') + ); } - public function test_get_locations_rejects_truncated_page_content(): void + public function test_equivalent_ipv6_reservation_marks_the_whole_ip_in_use(): void { - Http::fake([ - 'panel.example.com/*' => Http::response([ - 'data' => [], - 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], - ], 200), + $this->createCpuPolicy(); + $reservationId = $this->insertReservation( + 'ipv6-allocation-hold', + 'pending', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240] + ); + DB::table('ptero_reservation_allocations')->insert([ + 'reservation_id' => $reservationId, + 'panel_identity' => self::PANEL_IDENTITY, + 'node_id' => 5, + 'allocation_id' => 601, + 'ip' => '2001:db8::1', + 'port' => 25565, + 'is_primary' => true, + 'created_at' => now(), + 'updated_at' => now(), ]); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('incomplete pagination data'); + $node = $this->service(allocations: [[ + 'id' => 602, + 'ip' => '2001:0db8:0:0:0:0:0:1', + 'port' => 25566, + ]])->getLocationAvailability(1)['nodes'][0]; - $this->service->getLocations(); + $this->assertTrue($node['available_allocations'][0]['ip_in_use']); } - public function test_get_locations_rejects_inconsistent_total_pages(): void + public function test_pending_dedicated_hold_removes_its_whole_ip_from_all_stock(): void { - Http::fake(function ($request) { - $query = []; - parse_str(parse_url($request->url(), PHP_URL_QUERY) ?? '', $query); - $page = (int) ($query['page'] ?? 1); - - return Http::response([ - 'data' => [[ - 'attributes' => [ - 'id' => $page, - 'short' => 'dc'.$page, - 'long' => 'Data Center '.$page, - ], - ]], - 'meta' => [ - 'pagination' => [ - 'current_page' => $page, - 'count' => 1, - 'per_page' => 1, - 'total' => 3, - 'total_pages' => $page === 1 ? 3 : 2, - ], - ], - ], 200); - }); + $this->createCpuPolicy(); + $reservationId = $this->insertReservation( + 'dedicated-allocation-hold', + 'pending', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240] + ); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'configuration_payload' => json_encode([ + 'allocation_requirements' => ['dedicated_ip' => true], + ]), + ]); + DB::table('ptero_reservation_allocations')->insert([ + 'reservation_id' => $reservationId, + 'panel_identity' => self::PANEL_IDENTITY, + 'node_id' => 5, + 'allocation_id' => 502, + 'ip' => '192.0.2.5', + 'port' => 25566, + 'is_primary' => true, + 'created_at' => now(), + 'updated_at' => now(), + ]); + $service = $this->service(allocations: [ + ['id' => 501, 'ip' => '192.0.2.5', 'port' => 25565], + ['id' => 502, 'ip' => '192.0.2.5', 'port' => 25566], + ['id' => 503, 'ip' => '192.0.2.6', 'port' => 25565], + ]); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('inconsistent pagination metadata'); + $node = $service->getLocationAvailability(1)['nodes'][0]; + $this->assertSame( + [503], + array_column($node['available_allocations'], 'id') + ); - $this->service->getLocations(); + $editing = $service + ->getLocationAvailability(1, 'dedicated-allocation-hold')['nodes'][0]; + $this->assertSame( + [501, 502, 503], + array_column($editing['available_allocations'], 'id') + ); } - public function test_get_locations_rejects_malformed_location_payload(): void + public function test_confirmed_dedicated_server_blocks_ip_until_service_is_cancelled(): void { - Http::fake([ - 'panel.example.com/*' => Http::response([ - 'data' => [['attributes' => ['id' => 1, 'short' => 'dc1']]], - 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], - ], 200), + $this->createCpuPolicy(); + $serviceRecord = \App\Models\Service::factory()->create(); + DB::table('services')->where('id', $serviceRecord->id)->update([ + 'status' => \App\Models\Service::STATUS_ACTIVE, + ]); + $reservationId = $this->insertReservation( + 'confirmed-dedicated', + 'confirmed', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240] + ); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'service_id' => $serviceRecord->id, + 'configuration_payload' => json_encode([ + 'allocation_requirements' => ['dedicated_ip' => true], + ]), + ]); + DB::table('ptero_reservation_allocations')->insert([ + 'reservation_id' => $reservationId, + 'panel_identity' => self::PANEL_IDENTITY, + 'node_id' => 5, + 'allocation_id' => 501, + 'ip' => '192.0.2.5', + 'port' => 25565, + 'is_primary' => true, + 'released_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), + ]); + $stock = $this->service(allocations: [ + ['id' => 502, 'ip' => '192.0.2.5', 'port' => 25566], + ['id' => 503, 'ip' => '192.0.2.6', 'port' => 25565], ]); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('invalid location payload'); + $this->assertSame( + [503], + array_column( + $stock->getLocationAvailability(1)['nodes'][0]['available_allocations'], + 'id' + ) + ); - $this->service->getLocations(); + DB::table('services')->where('id', $serviceRecord->id)->update([ + 'status' => \App\Models\Service::STATUS_CANCELLED, + ]); + $this->assertSame( + [502, 503], + array_column( + $stock->getLocationAvailability(1)['nodes'][0]['available_allocations'], + 'id' + ) + ); } - public function test_get_locations_rejects_duplicate_location_records(): void + public function test_holds_from_another_panel_do_not_reduce_colliding_node_or_allocation_stock(): void { - Http::fake([ - 'panel.example.com/*' => Http::response([ - 'data' => [ - ['attributes' => ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], - ['attributes' => ['id' => 1, 'short' => 'dc1-copy', 'long' => 'Data Center 1 Copy']], - ], - 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 2, 100, 2)], - ], 200), + $this->createCpuPolicy(); + $reservationId = $this->insertReservation( + 'other-panel-hold', + 'pending', + ['memory' => 2048, 'cpu' => 100, 'disk' => 10240], + panelIdentity: str_repeat('f', 64) + ); + DB::table('ptero_reservation_allocations')->insert([ + 'reservation_id' => $reservationId, + 'panel_identity' => str_repeat('f', 64), + 'node_id' => 5, + 'allocation_id' => 501, + 'ip' => '192.0.2.5', + 'port' => 25565, + 'is_primary' => true, + 'created_at' => now(), + 'updated_at' => now(), ]); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('duplicate location'); + $node = $this->service()->getLocationAvailability(1)['nodes'][0]; - $this->service->getLocations(); + $this->assertSame( + ['memory' => 0, 'cpu' => 0, 'disk' => 0], + $node['reserved'] + ); + $this->assertSame( + [501], + array_column($node['available_allocations'], 'id') + ); } - public function test_snapshot_rejects_node_for_unknown_location(): void + public function test_fixed_node_upgrade_can_skip_new_allocation_but_not_other_eligibility_rules(): void { - $calls = 0; - Http::fake($this->clusterSnapshotHttpFake( - $calls, - locations: [['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], - nodePages: [[ - $this->nodeWithServersPayload(1, 2, 'Orphan Node', []), - ]], - )); - - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('unknown location'); - - $this->service->buildClusterSnapshot(); - } + $this->createCpuPolicy(); + $service = $this->service(allocations: []); - public function test_snapshot_rejects_duplicate_node_records(): void - { - $calls = 0; - Http::fake($this->clusterSnapshotHttpFake( - $calls, - locations: [['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], - nodePages: [[ - $this->nodeWithServersPayload(1, 1, 'Node 1', []), - $this->nodeWithServersPayload(1, 1, 'Node 1 Duplicate', []), - ]], + $this->assertTrue($service->verifyNodeCapacity( + 5, + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + allocationCount: 0 )); - - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('duplicate node'); - - $this->service->buildClusterSnapshot(); - } - - public function test_snapshot_rejects_duplicate_server_records(): void - { - $calls = 0; - Http::fake($this->clusterSnapshotHttpFake( - $calls, - locations: [['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], - nodePages: [[ - $this->nodeWithServersPayload(1, 1, 'Node 1', [ - ['id' => 101, 'memory' => 1024, 'cpu' => 50, 'disk' => 5120], - ['id' => 101, 'memory' => 1024, 'cpu' => 50, 'disk' => 5120], - ]), - ]], + $this->assertFalse($service->verifyAvailability( + 5, + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240] )); - - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('duplicate server'); - - $this->service->buildClusterSnapshot(); } - public function test_snapshot_handles_pterodactyl_5xx_gracefully(): void - { - $calls = 0; - - Http::fake(function ($request) use (&$calls) { - $calls++; - - if (str_contains($request->url(), '/api/application/locations')) { - return Http::response([ - 'data' => [ - ['attributes' => ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1']], - ], - 'meta' => ['pagination' => $this->paginationMetadata(1, 1, 1, 100, 1)], - ], 200); - } - - return Http::response(['errors' => [['detail' => 'panel down']]], 500); - }); - - $snapshot = $this->service->buildClusterSnapshot(); - - $this->assertSame('Pterodactyl unavailable', $snapshot['error']); - $this->assertSame([], $snapshot['nodes']); - $this->assertSame([], $snapshot['by_location']); - $this->assertLessThanOrEqual(4, $calls); - } - - public function test_snapshot_keeps_pterodactyl_call_count_constant(): void - { - $calls = 0; - $nodes = []; - - for ($nodeId = 1; $nodeId <= 55; $nodeId++) { - $nodes[] = $this->nodeWithServersPayload($nodeId, ($nodeId % 5) + 1, 'Node '.$nodeId, []); - } - - Http::fake($this->clusterSnapshotHttpFake( - $calls, - locations: [ - ['id' => 1, 'short' => 'dc1', 'long' => 'Data Center 1'], - ['id' => 2, 'short' => 'dc2', 'long' => 'Data Center 2'], - ['id' => 3, 'short' => 'dc3', 'long' => 'Data Center 3'], - ['id' => 4, 'short' => 'dc4', 'long' => 'Data Center 4'], - ['id' => 5, 'short' => 'dc5', 'long' => 'Data Center 5'], + /** + * @param list, + * allocation_headroom?: int + * }> $servers + * @param list|null $allocations + */ + private function service( + ?array $node = null, + array $servers = [], + ?array $allocations = null + ): ResourceCalculationService { + $node ??= $this->node(); + $allocations ??= [['id' => 501, 'ip' => '192.0.2.5', 'port' => 25565]]; + $inventory = Mockery::mock(PterodactylInventoryService::class); + $inventory->shouldReceive('panelIdentity') + ->zeroOrMoreTimes() + ->andReturn(self::PANEL_IDENTITY); + $inventory->shouldReceive('nodesInLocation') + ->zeroOrMoreTimes() + ->with(1) + ->andReturn([$node]); + $inventory->shouldReceive('nodes') + ->zeroOrMoreTimes() + ->andReturn([$node]); + $inventory->shouldReceive('serversForNodes') + ->zeroOrMoreTimes() + ->with([5]) + ->andReturn([5 => $servers]); + $inventory->shouldReceive('availableAllocationsForNode') + ->zeroOrMoreTimes() + ->with(5) + ->andReturn($allocations); + + return new ResourceCalculationService($inventory); + } + + /** + * @return array + */ + private function node(array $overrides = []): array + { + return array_replace_recursive([ + 'id' => 5, + 'uuid' => '00000000-0000-4000-8000-000000000005', + 'name' => 'Node 5', + 'fqdn' => 'node-5.example.com', + 'public' => true, + 'maintenance_mode' => false, + 'location_id' => 1, + 'memory' => 32768, + 'disk' => 512000, + 'memory_overallocate' => 0, + 'disk_overallocate' => 0, + 'allocated_resources' => [ + 'memory' => 0, + 'disk' => 0, ], - nodePages: [array_slice($nodes, 0, 50), array_slice($nodes, 50)], - )); - - $snapshot = $this->service->buildClusterSnapshot(); - - $this->assertCount(55, $snapshot['nodes']); - $this->assertLessThanOrEqual(4, $calls); + ], $overrides); + } + + private function createCpuPolicy( + int $capacity = 800, + int $overcommit = 10000 + ): NodeCapacityPolicy { + return NodeCapacityPolicy::query()->updateOrCreate([ + 'panel_identity' => self::PANEL_IDENTITY, + 'node_uuid' => '00000000-0000-4000-8000-000000000005', + ], [ + 'node_id' => 5, + 'location_id' => 1, + 'cpu_capacity_percent' => $capacity, + 'cpu_overcommit_bps' => $overcommit, + 'enabled' => true, + ]); } - private function insertPendingReservation(string $token, int $nodeId, int $locationId, array $resources): void - { - DB::table('ptero_resource_reservations')->insert([ + private function insertReservation( + string $token, + string $status, + array $resources, + mixed $expiresAt = null, + string $panelIdentity = self::PANEL_IDENTITY + ): int { + return DB::table('ptero_resource_reservations')->insertGetId([ 'token' => $token, - 'node_id' => $nodeId, - 'location_id' => $locationId, + 'panel_identity' => $panelIdentity, + 'node_id' => 5, + 'location_id' => 1, 'memory' => $resources['memory'], 'cpu' => $resources['cpu'], 'disk' => $resources['disk'], 'calculated_price' => 9.99, 'pricing_breakdown' => json_encode([]), - 'status' => 'pending', - 'expires_at' => \now()->addMinutes(15), - 'created_at' => \now(), - 'updated_at' => \now(), + 'status' => $status, + 'expires_at' => $expiresAt ?? now()->addMinutes(15), + 'created_at' => now(), + 'updated_at' => now(), ]); } - - private function availabilityHttpFake( - int $nodeId, - int $locationId, - int|float $totalMemory, - int $totalDisk, - int $totalCpuThreads, - array $servers = [], - array $additionalNodeIds = [], - ?int $includedNodeLocationId = null, - ): callable - { - return function ($request) use ($nodeId, $locationId, $totalMemory, $totalDisk, $totalCpuThreads, $servers, $additionalNodeIds, $includedNodeLocationId) { - $url = $request->url(); - $query = []; - parse_str(parse_url($url, PHP_URL_QUERY) ?? '', $query); - - if (str_contains($url, "/api/application/locations/{$locationId}") && ($query['include'] ?? null) === 'nodes,servers') { - return Http::response([ - 'object' => 'location', - 'attributes' => [ - 'id' => $locationId, - 'short' => 'dc'.$locationId, - 'long' => 'Data Center '.$locationId, - 'relationships' => [ - 'nodes' => [ - 'object' => 'list', - 'data' => array_map(fn (int $includedNodeId) => [ - 'object' => 'node', - 'attributes' => [ - 'id' => $includedNodeId, - 'location_id' => $includedNodeLocationId ?? $locationId, - 'name' => 'Node '.$includedNodeId, - 'fqdn' => 'node-'.$includedNodeId.'.example.com', - 'memory' => $totalMemory, - 'disk' => $totalDisk, - 'cpu_threads' => $totalCpuThreads, - 'memory_overallocate' => 0, - 'disk_overallocate' => 0, - 'maintenance_mode' => false, - 'allocated_resources' => [ - 'memory' => 0, - 'disk' => 0, - ], - ], - ], array_merge([$nodeId], $additionalNodeIds)), - ], - 'servers' => [ - 'object' => 'list', - 'data' => array_map(fn (array $server, int $index) => [ - 'object' => 'server', - 'attributes' => [ - 'id' => $server['id'] ?? (($server['node'] * 100) + $index), - 'node' => $server['node'], - 'limits' => array_intersect_key($server, [ - 'memory' => true, - 'cpu' => true, - 'disk' => true, - ]), - ], - ], $servers, array_keys($servers)), - ], - ], - ], - ], 200); - } - - if (str_ends_with($url, "/api/application/nodes/{$nodeId}")) { - return Http::response([ - 'attributes' => [ - 'id' => $nodeId, - 'location_id' => $locationId, - ], - ], 200); - } - - return Http::response([], 404); - }; - } - - private function clusterSnapshotHttpFake(int &$calls, array $locations, array $nodePages): callable - { - return function ($request) use (&$calls, $locations, $nodePages) { - $calls++; - - $url = $request->url(); - $query = []; - parse_str(parse_url($url, PHP_URL_QUERY) ?? '', $query); - - if (str_contains($url, '/api/application/locations') && ! preg_match('#/api/application/locations/\d+#', $url)) { - $locationPages = $this->isPaginatedPayload($locations) ? $locations : [$locations]; - $page = (int) ($query['page'] ?? 1); - - return Http::response([ - 'data' => array_map(fn (array $location) => ['attributes' => $location], $locationPages[$page - 1] ?? []), - 'meta' => ['pagination' => $this->paginationMetadataForPages($page, $locationPages)], - ], 200); - } - - if (str_contains($url, '/api/application/nodes')) { - $page = (int) ($query['page'] ?? 1); - - return Http::response([ - 'data' => $nodePages[$page - 1] ?? [], - 'meta' => ['pagination' => $this->paginationMetadataForPages($page, $nodePages)], - ], 200); - } - - return Http::response([], 404); - }; - } - - private function isPaginatedPayload(array $payload): bool - { - return isset($payload[0]) && is_array($payload[0]) && array_is_list($payload[0]); - } - - private function paginationMetadataForPages(int $page, array $pages): array - { - $perPage = max(1, count($pages[0] ?? [])); - $total = array_sum(array_map('count', $pages)); - - return $this->paginationMetadata( - $page, - max(1, count($pages)), - count($pages[$page - 1] ?? []), - $perPage, - $total, - ); - } - - private function paginationMetadata(int $currentPage, int $totalPages, int $count, int $perPage, int $total): array - { - return [ - 'count' => $count, - 'current_page' => $currentPage, - 'per_page' => $perPage, - 'total' => $total, - 'total_pages' => $totalPages, - ]; - } - - private function nodeWithServersPayload(int $nodeId, int $locationId, string $name, array $servers): array - { - return [ - 'attributes' => [ - 'id' => $nodeId, - 'location_id' => $locationId, - 'name' => $name, - 'fqdn' => 'node-'.$nodeId.'.example.com', - 'memory' => 8192, - 'disk' => 51200, - 'cpu_threads' => 4, - 'memory_overallocate' => 0, - 'disk_overallocate' => 0, - 'maintenance_mode' => false, - 'relationships' => [ - 'servers' => [ - 'data' => array_map(fn (array $server, int $index) => [ - 'attributes' => [ - 'id' => $server['id'] ?? (($nodeId * 100) + $index), - 'node' => $nodeId, - 'limits' => $server, - ], - ], $servers, array_keys($servers)), - ], - ], - ], - ]; - } } diff --git a/tests/Unit/ResourceQuoteServiceTest.php b/tests/Unit/ResourceQuoteServiceTest.php new file mode 100644 index 0000000..d847cb4 --- /dev/null +++ b/tests/Unit/ResourceQuoteServiceTest.php @@ -0,0 +1,301 @@ +quote( + requested: ['memory' => 32768, 'cpu' => 200, 'disk' => 51200], + nodes: [$this->node(1, 23552, 800, 512000)] + ); + + $this->assertTrue($quote['adjusted']); + $this->assertSame(23552, $quote['selection']['memory']); + $this->assertSame(23552, $quote['bounds']['memory']['max']); + $this->assertSame(10, $quote['bounds']['memory']['config_option_id']); + } + + public function test_live_stock_above_product_cap_keeps_32_gb_maximum(): void + { + $quote = $this->quote( + requested: ['memory' => 32768, 'cpu' => 200, 'disk' => 51200], + nodes: [$this->node(1, 102400, 800, 512000)] + ); + + $this->assertFalse($quote['adjusted']); + $this->assertSame(32768, $quote['selection']['memory']); + $this->assertSame(32768, $quote['bounds']['memory']['max']); + } + + public function test_live_bound_is_rounded_down_to_configured_step(): void + { + $quote = $this->quote( + requested: ['memory' => 32768, 'cpu' => 200, 'disk' => 51200], + nodes: [$this->node(1, 23000, 800, 512000)] + ); + + $this->assertSame(22528, $quote['selection']['memory']); + $this->assertSame(22528, $quote['bounds']['memory']['max']); + } + + public function test_bounds_never_combine_independent_maxima_from_different_nodes(): void + { + $quote = $this->quote( + requested: ['memory' => 32768, 'cpu' => 200, 'disk' => 102400], + nodes: [ + $this->node(1, 32768, 800, 51200), + $this->node(2, 16384, 800, 102400), + ] + ); + + $this->assertTrue($quote['adjusted']); + $this->assertSame([ + 'memory' => 32768, + 'cpu' => 200, + 'disk' => 51200, + ], $quote['selection']); + $this->assertSame(32768, $quote['bounds']['memory']['max']); + $this->assertSame( + 51200, + $quote['bounds']['disk']['max'], + 'Disk max must be conditional on the selected 32 GB RAM.' + ); + } + + public function test_port_count_is_part_of_node_feasibility(): void + { + $configuration = $this->configuration(); + $configuration['allocation_count'] = 2; + + $this->expectException(StockUnavailableException::class); + + $this->runQuote($configuration, [ + $this->node(1, 32768, 800, 512000, allocationCount: 1), + ]); + } + + public function test_explicit_product_port_is_part_of_quote_feasibility(): void + { + $configuration = $this->configuration(); + $configuration['required_ports'] = [25570]; + + $this->expectException(StockUnavailableException::class); + + $this->runQuote($configuration, [ + $this->node(1, 32768, 800, 512000), + ]); + } + + public function test_quote_and_reservation_share_deterministic_multi_ip_port_selection(): void + { + $configuration = $this->configuration(); + $configuration['required_ports'] = [25570]; + $node = $this->node(1, 32768, 800, 512000, allocationCount: 2); + $node['available_allocations'] = [ + ['id' => 100, 'ip' => '192.0.2.1', 'port' => 25570], + ['id' => 101, 'ip' => '192.0.2.2', 'port' => 25570], + ]; + + $product = new Product(); + $product->id = 99; + $configurations = Mockery::mock(ProductResourceConfigurationService::class); + $configurations->shouldReceive('forQuote') + ->once() + ->with($product, []) + ->andReturn($configuration); + $resources = Mockery::mock(ResourceCalculationService::class); + $resources->shouldReceive('getLocationAvailability') + ->twice() + ->with(1, null) + ->andReturn(['nodes' => [$node]]); + $allocations = new AllocationSelectionService(); + + $quote = (new ResourceQuoteService( + $configurations, + $resources, + $allocations + ))->quote($product, []); + $selectedNode = (new NodeSelectionService($resources, $allocations)) + ->selectBestNodeWithAllocations( + 1, + $configuration['resources'], + $configuration['allocation_count'], + null, + $configuration['required_ports'] + ); + + $this->assertTrue($quote['available']); + $this->assertSame( + [100], + array_column($selectedNode['selected_allocations'], 'id'), + 'Reservation placement must use the same deterministic set accepted by the quote.' + ); + } + + public function test_customer_quote_contains_no_node_identity(): void + { + $quote = $this->quote( + requested: ['memory' => 4096, 'cpu' => 200, 'disk' => 51200], + nodes: [$this->node(55, 32768, 800, 512000)] + ); + $encoded = json_encode($quote, JSON_THROW_ON_ERROR); + + $this->assertStringNotContainsString('node_id', $encoded); + $this->assertStringNotContainsString('fqdn', $encoded); + $this->assertStringNotContainsString('available_allocations', $encoded); + } + + /** + * @dataProvider unboundedInventoryReasons + */ + public function test_unbounded_inventory_is_configuration_failure(string $reason): void + { + $configuration = $this->configuration(); + $product = new Product(); + $product->id = 99; + $configurations = Mockery::mock(ProductResourceConfigurationService::class); + $configurations->shouldReceive('forQuote')->andReturn($configuration); + $resources = Mockery::mock(ResourceCalculationService::class); + $resources->shouldReceive('getLocationAvailability')->andReturn([ + 'nodes' => [[ + 'eligible' => false, + 'ineligible_reasons' => [$reason], + 'available_allocations' => [], + ]], + ]); + + $this->expectException(InvalidStockConfigurationException::class); + + (new ResourceQuoteService( + $configurations, + $resources, + new AllocationSelectionService() + )) + ->quote($product, []); + } + + public static function unboundedInventoryReasons(): array + { + return [ + 'missing CPU policy' => ['cpu_policy_missing'], + 'unbounded existing server' => ['unlimited_existing_resource'], + 'unbounded node memory' => ['unbounded_memory_overallocation'], + 'unbounded node disk' => ['unbounded_disk_overallocation'], + ]; + } + + private function quote(array $requested, array $nodes): array + { + $configuration = $this->configuration(); + $configuration['resources'] = $requested; + + return $this->runQuote($configuration, $nodes); + } + + private function runQuote(array $configuration, array $nodes): array + { + $product = new Product(); + $product->id = 99; + $configurations = Mockery::mock(ProductResourceConfigurationService::class); + $configurations->shouldReceive('forQuote') + ->once() + ->with($product, []) + ->andReturn($configuration); + $resources = Mockery::mock(ResourceCalculationService::class); + $resources->shouldReceive('getLocationAvailability') + ->once() + ->with(1, null) + ->andReturn(['nodes' => $nodes]); + + return (new ResourceQuoteService( + $configurations, + $resources, + new AllocationSelectionService() + )) + ->quote($product, []); + } + + private function configuration(): array + { + return [ + 'product_id' => 99, + 'location_id' => 1, + 'resources' => [ + 'memory' => 32768, + 'cpu' => 200, + 'disk' => 51200, + ], + 'sliders' => [ + 'memory' => [ + 'config_option_id' => 10, + 'min' => 1024, + 'max' => 32768, + 'step' => 1024, + 'default' => 4096, + ], + 'cpu' => [ + 'config_option_id' => 11, + 'min' => 100, + 'max' => 800, + 'step' => 100, + 'default' => 200, + ], + 'disk' => [ + 'config_option_id' => 12, + 'min' => 10240, + 'max' => 512000, + 'step' => 10240, + 'default' => 51200, + ], + ], + 'allocation_count' => 1, + 'required_ports' => [], + 'allocation_mappings' => [[ + 'environment_key' => 'SERVER_PORT', + 'requested_port' => null, + 'is_primary' => true, + ]], + ]; + } + + private function node( + int $nodeId, + int $memory, + int $cpu, + int $disk, + int $allocationCount = 1 + ): array { + return [ + 'node_id' => $nodeId, + 'eligible' => true, + 'available' => [ + 'memory' => $memory, + 'cpu' => $cpu, + 'disk' => $disk, + ], + 'available_allocations' => $allocationCount === 0 + ? [] + : array_map( + fn (int $offset): array => [ + 'id' => ($nodeId * 100) + $offset, + 'ip' => '192.0.2.'.$nodeId, + 'port' => 25565 + $offset, + ], + range(1, $allocationCount) + ), + ]; + } +} diff --git a/tests/Unit/SliderConfigReaderServiceTest.php b/tests/Unit/SliderConfigReaderServiceTest.php deleted file mode 100644 index 8158b1d..0000000 --- a/tests/Unit/SliderConfigReaderServiceTest.php +++ /dev/null @@ -1,134 +0,0 @@ -service = new SliderConfigReaderService(); - } - - public function test_get_config_returns_slider_info(): void - { - $product = Product::factory()->create(); - - $this->attachSlider($product, 'Memory', 'memory', [ - 'min' => 1024, - 'max' => 8192, - 'step' => 1024, - 'default' => 4096, - 'unit' => 'MB', - 'display_unit' => 'GB', - 'display_divisor' => 1024, - 'pricing' => ['model' => 'linear', 'rate_per_unit' => 2.00], - ]); - - $this->attachSlider($product, 'CPU', 'cpu', [ - 'min' => 100, - 'max' => 400, - 'step' => 100, - 'default' => 200, - 'unit' => '%', - 'display_unit' => 'cores', - 'display_divisor' => 100, - 'pricing' => ['model' => 'linear', 'rate_per_unit' => 3.00], - ]); - - $config = $this->service->getConfig($product->id); - - $this->assertTrue($config['has_config']); - $this->assertArrayHasKey('memory', $config['sliders']); - $this->assertArrayHasKey('cpu', $config['sliders']); - $this->assertEquals(1024, $config['sliders']['memory']['min']); - $this->assertEquals('GB', $config['sliders']['memory']['display_unit']); - } - - public function test_get_config_returns_empty_payload_when_no_sliders_exist(): void - { - $product = Product::factory()->create(); - - $config = $this->service->getConfig($product->id); - - $this->assertFalse($config['has_config']); - $this->assertSame([], $config['sliders']); - } - - public function test_service_resolves_from_container(): void - { - $this->assertInstanceOf(SliderConfigReaderService::class, app(SliderConfigReaderService::class)); - } - - private function attachSlider(Product $product, string $name, string $resourceType, array $metadata): void - { - $option = ConfigOption::create([ - 'name' => $name, - 'env_variable' => strtoupper($resourceType), - 'type' => 'dynamic_slider', - 'sort' => 0, - 'hidden' => false, - 'upgradable' => true, - 'metadata' => array_merge(['resource_type' => $resourceType], $metadata), - ]); - - DB::table('config_option_products')->insert([ - 'product_id' => $product->id, - 'config_option_id' => $option->id, - ]); - } - public function test_get_config_handles_json_encoded_metadata(): void - { - $product = Product::factory()->create(); - - $option = ConfigOption::create([ - 'name' => 'Memory', - 'env_variable' => 'MEMORY', - 'type' => 'dynamic_slider', - 'sort' => 0, - 'hidden' => false, - 'upgradable' => true, - 'metadata' => null, - ]); - - // Force a JSON string into the metadata column (simulates rows where cast is bypassed) - \Illuminate\Support\Facades\DB::table('config_options') - ->where('id', $option->id) - ->update(['metadata' => json_encode([ - 'resource_type' => 'memory', - 'min' => 1024, - 'max' => 8192, - 'step' => 1024, - 'default' => 4096, - 'unit' => 'MB', - 'display_unit' => 'GB', - 'display_divisor' => 1024, - 'pricing' => ['model' => 'linear', 'rate_per_unit' => 2.00], - ])]); - - DB::table('config_option_products')->insert([ - 'product_id' => $product->id, - 'config_option_id' => $option->id, - ]); - - $config = $this->service->getConfig($product->id); - - $this->assertTrue($config['has_config']); - $this->assertArrayHasKey('memory', $config['sliders']); - $this->assertEquals(1024, $config['sliders']['memory']['min']); - $this->assertEquals('GB', $config['sliders']['memory']['display_unit']); - } - -} diff --git a/tests/Unit/UpgradeReservationServiceTest.php b/tests/Unit/UpgradeReservationServiceTest.php new file mode 100644 index 0000000..9bfc777 --- /dev/null +++ b/tests/Unit/UpgradeReservationServiceTest.php @@ -0,0 +1,950 @@ +assertOrderedSourceMarkers($upgradeSource, [ + '$invoice = $candidate->invoice_id', + 'Service::query()', + '$upgrade = ServiceUpgrade::query()', + '$reservation = UpgradeReservation::query()', + '$invoice->items()', + ]); + $this->assertOrderedSourceMarkers($checkoutSource, [ + '$invoice = $candidate->invoice_id', + '$services = Service::query()', + '$reservations = DB::table(', + '$lockedItems = $invoice !== null', + ]); + } + + use DatabaseTransactions; + + protected function tearDown(): void + { + Mockery::close(); + + parent::tearDown(); + } + + public function test_fixed_node_quote_clamps_32_gb_to_23_gb_and_accepts_select_key(): void + { + $fixture = $this->fixture(); + + $quote = $fixture->upgrades->quoteForService( + $fixture->service, + [ + $fixture->options['memory']->id => 32768, + $fixture->options['cpu']->id => 200, + $fixture->options['disk']->id => 20480, + $fixture->select->id => $fixture->selectChild->id, + ] + ); + + $this->assertTrue($quote['adjusted']); + $this->assertSame(23552, $quote['selection']['memory']); + $this->assertSame(23552, $quote['bounds']['memory']['max']); + } + + public function test_duplicate_active_resource_slider_fails_closed_but_hidden_one_does_not(): void + { + $fixture = $this->fixture(); + $duplicate = $this->option( + $fixture->product, + 'memory', + 1024, + 32768, + 1024, + 4096 + ); + + try { + $fixture->upgrades->quoteForService( + $fixture->service, + $this->selection($fixture) + ); + $this->fail('Expected duplicate memory sliders to fail closed.'); + } catch (InvalidStockConfigurationException $exception) { + $this->assertStringContainsString( + 'Multiple active memory', + $exception->getMessage() + ); + } + + $duplicate->hidden = true; + $duplicate->save(); + $fixture->service->unsetRelation('product'); + + $quote = $fixture->upgrades->quoteForService( + $fixture->service, + $this->selection($fixture) + ); + $this->assertSame(23552, $quote['bounds']['memory']['max']); + } + + public function test_upgrade_reserves_only_positive_delta_but_keeps_full_target(): void + { + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + + $this->assertSame(8192, (int) $reservation->memory); + $this->assertSame(100, (int) $reservation->cpu); + $this->assertSame(30720, (int) $reservation->disk); + $this->assertSame(4096, (int) $reservation->reserved_memory); + $this->assertSame(0, (int) $reservation->reserved_cpu); + $this->assertSame(10240, (int) $reservation->reserved_disk); + $this->assertSame(99, (int) $reservation->external_server_id); + $this->assertSame(44, (int) $reservation->external_user_id); + $this->assertSame( + '10000000-0000-4000-8000-000000000099', + $reservation->external_server_uuid + ); + $this->assertSame( + 'server-99', + $reservation->external_server_identifier + ); + } + + public function test_unchanged_resource_vector_is_not_an_upgrade(): void + { + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + foreach ([ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + ] as $resource => $value) { + $upgrade->configs() + ->where('config_option_id', $fixture->options[$resource]->id) + ->update(['slider_value' => $value]); + } + $this->recaptureUpgrade($upgrade); + + $this->expectException(InvalidResourceSelectionException::class); + $this->expectExceptionMessage('must change at least one'); + + $fixture->upgrades->reserveForUpgrade( + $upgrade->fresh(), + $invoice->due_at + ); + } + + public function test_checkout_identity_survives_product_and_customer_email_edits(): void + { + $fixture = $this->fixture(); + $checkoutEmail = strtolower((string) $fixture->user->email); + $fixture->user->update([ + 'email' => "renamed-{$fixture->user->id}@example.com", + ]); + $fixture->product->settings()->updateOrCreate( + ['key' => 'nest_id'], + ['value' => 77, 'type' => 'integer', 'encrypted' => false] + ); + $fixture->product->settings()->updateOrCreate( + ['key' => 'egg_id'], + ['value' => 88, 'type' => 'integer', 'encrypted' => false] + ); + $fixture->service->unsetRelation('product'); + $fixture->service->unsetRelation('user'); + [$upgrade, $invoice] = $this->upgrade($fixture); + + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + $payload = (array) $reservation->configuration_payload; + + $this->assertSame(1, $payload['nest_id']); + $this->assertSame(2, $payload['egg_id']); + $this->assertSame($checkoutEmail, $payload['user_email']); + } + + public function test_server_identity_drift_is_rejected_before_upgrade_reservation(): void + { + $mutations = [ + ['uuid', '20000000-0000-4000-8000-000000000099'], + ['identifier', 'replacement-server'], + ['external_id', 'another-service'], + ['user_id', 45], + ['user_external_id', 'paymenter-user-999'], + ['nest_id', 7], + ['egg_id', 8], + ]; + + foreach ($mutations as [$field, $value]) { + $fixture = $this->fixture(); + $fixture->remote->server[$field] = $value; + [$upgrade, $invoice] = $this->upgrade($fixture); + + try { + $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + $this->fail("Expected {$field} drift to fail closed."); + } catch (InvalidResourceSelectionException $exception) { + $this->assertStringContainsString( + 'immutable checkout commitment', + $exception->getMessage() + ); + } + } + } + + public function test_paid_upgrade_commit_returns_explicit_handled_proof(): void + { + Queue::fake(); + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + + $this->assertTrue( + $fixture->upgrades->commitPaidUpgrade($upgrade, $invoice) + ); + $this->assertSame( + 'paid_committed', + $reservation->fresh()->status + ); + $this->assertSame( + ServiceUpgrade::STATUS_PAID_COMMITTED, + $upgrade->fresh()->status + ); + } + + public function test_dynamic_upgrade_rejects_non_resource_configuration_change(): void + { + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $upgrade->configs()->create([ + 'config_option_id' => $fixture->select->id, + 'config_value_id' => $fixture->selectChild->id, + 'slider_value' => null, + ]); + $upgrade->unsetRelation('configs'); + $upgrade->load([ + 'service.product.server.settings', + 'service.product.settings', + 'service.configs.configOption', + 'service.configs.configValue', + 'product.server.settings', + 'product.settings', + 'plan.prices', + 'configs.configOption', + 'configs.configValue', + ]); + $upgrade->captureSnapshots(); + $upgrade->save(); + + $this->expectException(InvalidResourceSelectionException::class); + $this->expectExceptionMessage( + 'may change only RAM, CPU, and disk' + ); + + $fixture->upgrades->reserveForUpgrade($upgrade, $invoice->due_at); + } + + public function test_old_worker_cannot_clear_newer_upgrade_lease(): void + { + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + $reservation->forceFill([ + 'status' => 'paid_committed', + 'provisioning_lease_id' => 'new-worker', + 'provisioning_started_at' => now(), + ])->save(); + + $this->assertFalse($fixture->upgrades->failProvisioning( + $upgrade, + new \RuntimeException('old worker failed'), + 'old-worker' + )); + $this->assertSame( + 'new-worker', + $reservation->fresh()->provisioning_lease_id + ); + + $this->assertTrue($fixture->upgrades->failProvisioning( + $upgrade, + new \RuntimeException('current worker failed'), + 'new-worker' + )); + $this->assertNull($reservation->fresh()->provisioning_lease_id); + } + + public function test_paid_upgrade_payload_is_verified_before_leasing(): void + { + Queue::fake(); + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + $fixture->upgrades->commitPaidUpgrade($upgrade, $invoice); + + $payload = (array) $reservation->fresh()->configuration_payload; + $payload['target']['memory'] = 16384; + DB::table('ptero_resource_reservations') + ->whereKey($reservation->id) + ->update([ + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + ]); + + try { + $fixture->upgrades->beginProvisioning($upgrade->fresh()); + $this->fail( + 'Expected a mutated paid upgrade payload to fail closed.' + ); + } catch (PermanentProvisioningException $exception) { + $this->assertStringContainsString( + 'immutable integrity', + $exception->getMessage() + ); + } + + $this->assertNull( + $reservation->fresh()->provisioning_lease_id + ); + } + + public function test_tampered_upgrade_payload_is_rejected_before_payment(): void + { + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + $payload = (array) $reservation->configuration_payload; + $payload['target']['memory'] = 16384; + DB::table('ptero_resource_reservations') + ->whereKey($reservation->id) + ->update([ + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + ]); + + $failure = $fixture->upgrades->preflightPaidUpgrade( + $upgrade, + $invoice + ); + + $this->assertStringContainsString( + 'immutable integrity', + strtolower((string) $failure) + ); + $this->assertSame( + ServiceUpgrade::STATUS_CANCELLED, + $upgrade->fresh()->status + ); + $this->assertSame(Invoice::STATUS_CANCELLED, $invoice->fresh()->status); + $this->assertSame('cancelled', $reservation->fresh()->status); + } + + public function test_tampered_invoice_line_is_cancelled_before_paid_transition(): void + { + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + $invoice->items()->firstOrFail()->update(['price' => 1]); + + $failure = $fixture->upgrades->preflightPaidUpgrade( + $upgrade, + $invoice + ); + $this->assertStringContainsString( + 'invoice line', + strtolower((string) $failure) + ); + + $this->assertSame( + ServiceUpgrade::STATUS_CANCELLED, + $upgrade->fresh()->status + ); + $this->assertSame(Invoice::STATUS_CANCELLED, $invoice->fresh()->status); + $this->assertSame('cancelled', $reservation->fresh()->status); + } + + public function test_renewal_after_quote_invalidates_upgrade_before_payment(): void + { + $fixture = $this->fixture(); + $fixture->service->expires_at = now()->addDays(10); + $fixture->service->save(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + + // Simulate the current service renewing on its old resource vector. + $fixture->service->expires_at = now()->addDays(35); + $fixture->service->save(); + + $failure = $fixture->upgrades->preflightPaidUpgrade( + $upgrade, + $invoice + ); + $this->assertStringContainsString( + 'service changed', + strtolower((string) $failure) + ); + + $this->assertSame( + ServiceUpgrade::STATUS_CANCELLED, + $upgrade->fresh()->status + ); + $this->assertSame(Invoice::STATUS_CANCELLED, $invoice->fresh()->status); + $this->assertSame('cancelled', $reservation->fresh()->status); + } + + public function test_add_payment_preserves_rejected_upgrade_attention_and_payment_evidence(): void + { + Queue::fake(); + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + + // Simulate renewal/admin drift beneath the model guard so the real + // synchronous payment listener encounters a stale immutable source. + DB::table('services') + ->where('id', $fixture->service->id) + ->update([ + 'price' => '11.00', + 'updated_at' => now(), + ]); + + ExtensionHelper::addPayment( + $invoice->id, + null, + '100.00', + transactionId: 'paid-but-stale-upgrade' + ); + + $this->assertDatabaseHas('invoice_transactions', [ + 'invoice_id' => $invoice->id, + 'transaction_id' => 'paid-but-stale-upgrade', + 'status' => InvoiceTransactionStatus::Succeeded->value, + ]); + $this->assertSame(Invoice::STATUS_PENDING, $invoice->fresh()->status); + $this->assertNotNull( + $invoice->fresh()->payment_attention_required_at + ); + $this->assertStringContainsString( + 'refund or account-credit review', + (string) $invoice->fresh()->payment_attention_reason + ); + $this->assertSame( + ServiceUpgrade::STATUS_NEEDS_ATTENTION, + $upgrade->fresh()->status + ); + $this->assertSame('cancelled', $reservation->fresh()->status); + $this->assertNull($reservation->fresh()->upgrade_guard_id); + Queue::assertNotPushed(UpgradeJob::class); + } + + public function test_expiry_with_partial_payment_releases_delta_and_requires_attention(): void + { + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + $reservation->forceFill([ + 'expires_at' => now()->subSecond(), + 'guaranteed_until' => now()->subSecond(), + ])->save(); + InvoiceTransaction::create([ + 'invoice_id' => $invoice->id, + 'amount' => 1, + 'fee' => 0, + 'status' => InvoiceTransactionStatus::Processing, + ]); + + $this->assertSame(1, $fixture->upgrades->expireUnpaidUpgrades()); + $this->assertSame('expired', $reservation->fresh()->status); + $this->assertSame( + ServiceUpgrade::STATUS_NEEDS_ATTENTION, + $upgrade->fresh()->status + ); + $this->assertSame(Invoice::STATUS_PENDING, $invoice->fresh()->status); + $this->assertNotNull( + $invoice->fresh()->payment_attention_required_at + ); + } + + private function fixture(): object + { + $user = User::factory()->create(); + $server = Server::create([ + 'name' => 'Pterodactyl', + 'extension' => 'Pterodactyl', + 'type' => 'server', + 'enabled' => true, + ]); + $server->settings()->create([ + 'key' => 'host', + 'value' => 'https://panel.example', + 'type' => 'string', + 'encrypted' => false, + ]); + $product = Product::factory()->create([ + 'server_id' => $server->id, + 'hidden' => false, + ]); + $product->settings()->create([ + 'key' => 'location_ids', + 'value' => [1], + 'type' => 'array', + 'encrypted' => false, + ]); + foreach (['nest_id' => 1, 'egg_id' => 2] as $key => $value) { + $product->settings()->create([ + 'key' => $key, + 'value' => $value, + 'type' => 'integer', + 'encrypted' => false, + ]); + } + $plan = Plan::factory()->create([ + 'priceable_id' => $product->id, + 'priceable_type' => Product::class, + 'name' => 'Monthly', + 'billing_unit' => 'month', + 'billing_period' => 1, + 'type' => 'recurring', + ]); + Price::factory()->create([ + 'plan_id' => $plan->id, + 'price' => 10, + 'setup_fee' => 0, + 'currency_code' => 'USD', + ]); + + // Create the service while the product is still non-dynamic; the + // production checkout creates dynamic services through its coordinator. + $service = Service::factory()->create([ + 'user_id' => $user->id, + 'product_id' => $product->id, + 'plan_id' => $plan->id, + 'quantity' => 1, + 'price' => 10, + 'currency_code' => 'USD', + 'status' => Service::STATUS_ACTIVE, + ]); + $options = [ + 'memory' => $this->option( + $product, + 'memory', + 1024, + 32768, + 1024, + 4096 + ), + 'cpu' => $this->option( + $product, + 'cpu', + 100, + 800, + 100, + 200 + ), + 'disk' => $this->option( + $product, + 'disk', + 10240, + 102400, + 10240, + 20480 + ), + ]; + foreach ([ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + ] as $resource => $value) { + ServiceConfig::create([ + 'configurable_id' => $service->id, + 'configurable_type' => Service::class, + 'config_option_id' => $options[$resource]->id, + 'config_value_id' => null, + 'slider_value' => $value, + ]); + } + $select = ConfigOption::create([ + 'name' => 'Template', + 'env_variable' => 'template', + 'type' => 'select', + 'hidden' => false, + 'upgradable' => true, + ]); + ConfigOptionProduct::create([ + 'product_id' => $product->id, + 'config_option_id' => $select->id, + ]); + $selectChild = ConfigOption::create([ + 'name' => 'Default', + 'env_variable' => 'default', + 'type' => 'option', + 'hidden' => false, + 'parent_id' => $select->id, + ]); + + $panelIdentity = hash('sha256', 'https://panel.example'); + $checkoutEmail = strtolower((string) $user->email); + $checkoutPayload = [ + 'customer_id' => (int) $user->id, + 'product_id' => (int) $product->id, + 'plan_id' => (int) $plan->id, + 'panel_identity' => $panelIdentity, + 'node_id' => 1, + 'resources' => [ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + ], + 'provisioning_identity' => [ + 'nest_id' => 1, + 'egg_id' => 2, + 'user_external_id' => "paymenter-user-{$user->id}", + 'user_email' => $checkoutEmail, + ], + ]; + $checkoutConfiguration = new ReservationConfigurationService; + DB::table('ptero_resource_reservations')->insert([ + 'purpose' => 'checkout', + 'token' => hash('sha256', "checkout:{$service->id}"), + 'service_id' => $service->id, + 'service_guard_id' => $service->id, + 'user_id' => $user->id, + 'node_id' => 1, + 'location_id' => 1, + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + 'reserved_memory' => 4096, + 'reserved_cpu' => 200, + 'reserved_disk' => 20480, + 'calculated_price' => 10, + 'pricing_breakdown' => json_encode([], JSON_THROW_ON_ERROR), + 'status' => 'confirmed', + 'expires_at' => now()->addDays(30), + 'guaranteed_until' => now()->addDays(30), + 'panel_identity' => $panelIdentity, + 'product_id' => $product->id, + 'plan_id' => $plan->id, + 'quantity' => 1, + 'currency_code' => 'USD', + 'configuration_fingerprint' => + $checkoutConfiguration->fingerprint($checkoutPayload), + 'configuration_payload' => json_encode( + $checkoutPayload, + JSON_THROW_ON_ERROR + ), + 'pricing_version' => str_repeat('a', 64), + 'formula_version' => + ReservationConfigurationService::FORMULA_VERSION, + 'external_server_id' => 99, + 'external_user_id' => 44, + 'external_server_uuid' => + '10000000-0000-4000-8000-000000000099', + 'external_server_identifier' => 'server-99', + 'consumed_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), + ]); + + $remote = (object) ['server' => [ + 'id' => 99, + 'uuid' => '10000000-0000-4000-8000-000000000099', + 'identifier' => 'server-99', + 'external_id' => (string) $service->id, + 'user_id' => 44, + 'user_external_id' => "paymenter-user-{$user->id}", + 'user_email' => $checkoutEmail, + 'nest_id' => 1, + 'egg_id' => 2, + 'node' => 1, + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + 'swap' => 0, + 'io' => 500, + 'threads' => null, + 'database_limit' => 2, + 'allocation_limit' => 0, + 'backup_limit' => 3, + 'allocation' => 123, + 'assigned_allocation_ids' => [123], + ]]; + $inventory = Mockery::mock(PterodactylInventoryService::class); + $inventory->shouldReceive('assertExclusiveProvisioningControl') + ->zeroOrMoreTimes(); + $inventory->shouldReceive('panelIdentity') + ->zeroOrMoreTimes() + ->andReturn($panelIdentity); + $inventory->shouldReceive('serverByExternalId') + ->zeroOrMoreTimes() + ->with($service->id) + ->andReturnUsing(fn (): array => $remote->server); + $inventory->shouldReceive('nodes')->zeroOrMoreTimes()->andReturn([[ + 'id' => 1, + 'uuid' => 'node-1', + 'location_id' => 1, + ]]); + $resources = Mockery::mock(ResourceCalculationService::class); + $resources->shouldReceive('getNodeAvailability') + ->zeroOrMoreTimes() + ->with(1) + ->andReturn([ + 'available' => [ + 'memory' => 19456, + 'cpu' => 600, + 'disk' => 512000, + ], + ]); + $resources->shouldReceive('verifyNodeCapacity') + ->zeroOrMoreTimes() + ->andReturn(true); + + return (object) [ + 'user' => $user, + 'server' => $server, + 'product' => $product, + 'plan' => $plan, + 'service' => $service, + 'options' => $options, + 'select' => $select, + 'selectChild' => $selectChild, + 'remote' => $remote, + 'upgrades' => new UpgradeReservationService( + $inventory, + $resources + ), + ]; + } + + private function upgrade(object $fixture): array + { + $dueAt = now()->addDays(7); + $invoice = Invoice::factory()->create([ + 'user_id' => $fixture->user->id, + 'currency_code' => 'USD', + 'status' => Invoice::STATUS_PENDING, + 'due_at' => $dueAt, + ]); + $upgrade = ServiceUpgrade::create([ + 'service_id' => $fixture->service->id, + 'product_id' => $fixture->product->id, + 'plan_id' => $fixture->plan->id, + 'invoice_id' => $invoice->id, + 'status' => ServiceUpgrade::STATUS_AWAITING_PAYMENT, + 'active_service_guard_id' => $fixture->service->id, + 'quoted_amount' => 100, + 'currency_code' => 'USD', + ]); + foreach ([ + 'memory' => 8192, + 'cpu' => 100, + 'disk' => 30720, + ] as $resource => $value) { + $upgrade->configs()->create([ + 'config_option_id' => $fixture->options[$resource]->id, + 'config_value_id' => null, + 'slider_value' => $value, + ]); + } + $upgrade->load([ + 'service.product.server.settings', + 'service.product.settings', + 'service.configs.configOption', + 'service.configs.configValue', + 'product.server.settings', + 'product.settings', + 'plan.prices', + 'configs.configOption', + 'configs.configValue', + ]); + $upgrade->captureSnapshots(); + $upgrade->save(); + $invoice->items()->create([ + 'description' => 'Resource upgrade', + 'price' => 100, + 'quantity' => 1, + 'reference_id' => $upgrade->id, + 'reference_type' => ServiceUpgrade::class, + ]); + + return [$upgrade->fresh(), $invoice->fresh()]; + } + + private function recaptureUpgrade(ServiceUpgrade $upgrade): void + { + $upgrade->unsetRelations(); + $upgrade->load([ + 'service.product.server.settings', + 'service.product.settings', + 'service.configs.configOption', + 'service.configs.configValue', + 'product.server.settings', + 'product.settings', + 'plan.prices', + 'configs.configOption', + 'configs.configValue', + ]); + $upgrade->captureSnapshots(); + $upgrade->save(); + } + + private function option( + Product $product, + string $resource, + int $min, + int $max, + int $step, + int $default + ): ConfigOption { + $option = ConfigOption::create([ + 'name' => ucfirst($resource), + 'env_variable' => $resource, + 'type' => 'dynamic_slider', + 'hidden' => false, + 'upgradable' => true, + 'metadata' => [ + 'managed_by' => 'dynamic_pterodactyl', + 'managed_product_id' => $product->id, + 'resource_type' => $resource, + 'min' => $min, + 'max' => $max, + 'step' => $step, + 'default' => $default, + 'display_divisor' => 1, + 'pricing' => [ + 'model' => 'linear', + 'rate_per_unit' => 1, + ], + ], + ]); + ConfigOptionProduct::create([ + 'product_id' => $product->id, + 'config_option_id' => $option->id, + ]); + + return $option; + } + + private function selection(object $fixture): array + { + return [ + $fixture->options['memory']->id => 32768, + $fixture->options['cpu']->id => 200, + $fixture->options['disk']->id => 20480, + $fixture->select->id => $fixture->selectChild->id, + ]; + } + + /** + * @param list $markers + */ + private function assertOrderedSourceMarkers( + string $source, + array $markers + ): void { + $previous = -1; + foreach ($markers as $marker) { + $position = strpos($source, $marker); + $this->assertNotFalse( + $position, + "Missing lock-order marker: {$marker}" + ); + $this->assertGreaterThan( + $previous, + $position, + "Lock-order marker is out of order: {$marker}" + ); + $previous = $position; + } + } +} From f7dde56c3e8e2d196b1378ad0fb2eded7b4ebbf1 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 07:23:28 +1000 Subject: [PATCH 37/95] test(ci): run core provisioning seams with extension --- .../cross-repository-integration.yml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml index 71bc1a8..008df84 100644 --- a/.github/workflows/cross-repository-integration.yml +++ b/.github/workflows/cross-repository-integration.yml @@ -86,6 +86,14 @@ jobs: DB_DATABASE: database/paymenter_test.sqlite run: vendor/bin/phpunit -c extensions/Others/DynamicPterodactyl/phpunit.xml + - name: Run Paymenter provisioning seam tests on SQLite + working-directory: paymenter + env: + APP_ENV: testing + DB_CONNECTION: sqlite + DB_DATABASE: database/paymenter_test.sqlite + run: vendor/bin/phpunit tests/Unit/PterodactylReservationIntegrationTest.php + extension: name: PHP ${{ matrix.php }} / MariaDB ${{ matrix.mariadb }} runs-on: ubuntu-latest @@ -180,3 +188,15 @@ jobs: DB_USERNAME: root DB_PASSWORD: password run: vendor/bin/phpunit -c extensions/Others/DynamicPterodactyl/phpunit.xml + + - name: Run Paymenter provisioning seam tests + working-directory: paymenter + env: + APP_ENV: testing + DB_CONNECTION: mariadb + DB_HOST: 127.0.0.1 + DB_PORT: 3306 + DB_DATABASE: paymenter_test + DB_USERNAME: root + DB_PASSWORD: password + run: vendor/bin/phpunit tests/Unit/PterodactylReservationIntegrationTest.php From cb8d7c7f552ee707c72933cbda8436377e51ff1b Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 07:41:47 +1000 Subject: [PATCH 38/95] fix(stock): harden lazy inventory and integration fixtures Defer panel credentials until an inventory operation, accept empty initial quote vectors, repair the readiness artifact, and align the PHP 12 cross-repository fixtures. --- Http/Requests/ResourceQuoteRequest.php | 2 +- .../ProductResourceConfigurationService.php | 13 +- Services/ResourceCalculationService.php | 31 +++-- migration-readiness.php | 2 +- tests/Unit/ReservationServiceTest.php | 47 ++++++- tests/Unit/ResourceCalculationServiceTest.php | 25 +++- tests/Unit/ResourceQuoteServiceTest.php | 10 +- tests/Unit/UpgradeReservationServiceTest.php | 125 ++++++++++-------- 8 files changed, 166 insertions(+), 89 deletions(-) diff --git a/Http/Requests/ResourceQuoteRequest.php b/Http/Requests/ResourceQuoteRequest.php index d3833a9..3b3e436 100644 --- a/Http/Requests/ResourceQuoteRequest.php +++ b/Http/Requests/ResourceQuoteRequest.php @@ -16,7 +16,7 @@ public function authorize(): bool public function rules(): array { return [ - 'config_options' => ['required', 'array', 'max:50'], + 'config_options' => ['present', 'array', 'max:50'], 'cart_item_id' => [ 'nullable', 'integer', diff --git a/Services/ProductResourceConfigurationService.php b/Services/ProductResourceConfigurationService.php index b7a7cc8..6d8d25d 100644 --- a/Services/ProductResourceConfigurationService.php +++ b/Services/ProductResourceConfigurationService.php @@ -13,11 +13,11 @@ class ProductResourceConfigurationService { - private PterodactylInventoryService $inventory; + private ?PterodactylInventoryService $inventory; public function __construct(?PterodactylInventoryService $inventory = null) { - $this->inventory = $inventory ?? app(PterodactylInventoryService::class); + $this->inventory = $inventory; } /** @@ -68,7 +68,7 @@ public function forQuote(Product $product, array $submittedOptions): array if ( $provisioningUrl === '' || ! hash_equals( - $this->inventory->panelIdentity(), + $this->inventory()->panelIdentity(), hash('sha256', $provisioningUrl) ) ) { @@ -76,7 +76,7 @@ public function forQuote(Product $product, array $submittedOptions): array 'The product and stock service are not configured for the same Pterodactyl panel.' ); } - $this->inventory->assertExclusiveProvisioningControl(); + $this->inventory()->assertExclusiveProvisioningControl(); $selected = $this->normalizeSubmittedOptions($submittedOptions); $activeOptions = $this->activeProductOptions($product); @@ -676,4 +676,9 @@ private function normalizePanelUrl(string $url): string return ''; } } + + private function inventory(): PterodactylInventoryService + { + return $this->inventory ??= app(PterodactylInventoryService::class); + } } diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index faf017c..1b14901 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -8,11 +8,11 @@ class ResourceCalculationService { - private PterodactylInventoryService $inventory; + private ?PterodactylInventoryService $inventory; public function __construct(?PterodactylInventoryService $inventory = null) { - $this->inventory = $inventory ?? app(PterodactylInventoryService::class); + $this->inventory = $inventory; } /** @@ -31,7 +31,7 @@ public function getLocationAvailability( int $locationId, ?string $excludeReservationToken = null ): array { - $nodes = $this->inventory->nodesInLocation($locationId); + $nodes = $this->inventory()->nodesInLocation($locationId); return $this->buildLocationAvailability( $locationId, @@ -48,8 +48,8 @@ public function buildClusterSnapshot(): array $snapshot = $this->emptyClusterSnapshot(); try { - $locations = $this->inventory->locations(); - $nodes = $this->inventory->nodes(); + $locations = $this->inventory()->locations(); + $nodes = $this->inventory()->nodes(); } catch (\RuntimeException $exception) { if ($this->shouldReturnDegradedSnapshot($exception)) { return $this->degradedClusterSnapshot(); @@ -178,7 +178,7 @@ public function getNodeAvailability( int $nodeId, ?string $excludeReservationToken = null ): ?array { - $node = collect($this->inventory->nodes())->firstWhere('id', $nodeId); + $node = collect($this->inventory()->nodes())->firstWhere('id', $nodeId); if (! is_array($node)) { return null; } @@ -197,12 +197,12 @@ public function getNodeAvailability( */ public function getLocations(): array { - return $this->inventory->locations(); + return $this->inventory()->locations(); } public function testConnection(): array { - return $this->inventory->testConnection(); + return $this->inventory()->testConnection(); } /** @@ -215,7 +215,7 @@ private function buildLocationAvailability( ?string $excludeReservationToken = null ): array { $nodeIds = array_map(fn (array $node): int => (int) $node['id'], $nodes); - $servers = $this->inventory->serversForNodes($nodeIds); + $servers = $this->inventory()->serversForNodes($nodeIds); $reservations = $this->holdingReservations( $nodeIds, $servers, @@ -250,7 +250,7 @@ private function buildLocationAvailability( ->values() ->all(); $inventoryAllocations = - $this->inventory->availableAllocationsForNode($nodeId); + $this->inventory()->availableAllocationsForNode($nodeId); $assignedServerIps = collect($inventoryAllocations) ->filter( fn (array $allocation): bool => in_array( @@ -552,7 +552,7 @@ private function cpuPolicies(array $nodes): array } return NodeCapacityPolicy::query() - ->forPanel($this->inventory->panelIdentity()) + ->forPanel($this->inventory()->panelIdentity()) ->whereIn('node_uuid', $uuids) ->get() ->keyBy('node_uuid') @@ -587,7 +587,7 @@ private function holdingReservations( ) ->where( 'reservations.panel_identity', - $this->inventory->panelIdentity() + $this->inventory()->panelIdentity() ) ->whereIn('reservations.node_id', $nodeIds) ->where(function ($query): void { @@ -917,7 +917,7 @@ private function reservedAllocationClaims( ) ->where( 'reservations.panel_identity', - $this->inventory->panelIdentity() + $this->inventory()->panelIdentity() ) ->whereColumn( 'allocations.panel_identity', @@ -1065,4 +1065,9 @@ private function shouldReturnDegradedSnapshot(\Throwable $exception): bool return str_contains($exception->getMessage(), 'connection failed') || preg_match('/inventory API error \\(5\\d\\d\\)/', $exception->getMessage()) === 1; } + + private function inventory(): PterodactylInventoryService + { + return $this->inventory ??= app(PterodactylInventoryService::class); + } } diff --git a/migration-readiness.php b/migration-readiness.php index 4ba87a2..685f583 100644 --- a/migration-readiness.php +++ b/migration-readiness.php @@ -668,4 +668,4 @@ private function requirePositive( $missing[] = $field; } } -} +}; diff --git a/tests/Unit/ReservationServiceTest.php b/tests/Unit/ReservationServiceTest.php index 78d2bcc..1f06a0c 100644 --- a/tests/Unit/ReservationServiceTest.php +++ b/tests/Unit/ReservationServiceTest.php @@ -8,6 +8,7 @@ use App\Models\ConfigOption; use App\Models\Extension; use App\Models\Invoice; +use App\Models\Plan; use App\Models\Product; use App\Models\Server; use App\Models\Service; @@ -354,7 +355,7 @@ public function test_pending_commitment_keeps_its_snapshot_while_future_child_pr $price->price = 7; $price->save(); - $this->assertSame('7.00', (string) $price->fresh()->price); + $this->assertEquals(7.0, (float) $price->fresh()->price); } public function test_pending_commitment_prevents_detaching_its_configuration(): void @@ -904,9 +905,18 @@ public function test_payment_after_the_seven_day_guarantee_fails_closed(): void $invoice = Invoice::factory()->create([ 'user_id' => $service->user_id, 'status' => Invoice::STATUS_PENDING, + 'currency_code' => 'USD', + ]); + $invoice->items()->create([ + 'reference_type' => Service::class, + 'reference_id' => $service->id, + 'price' => 12.50, + 'quantity' => 1, + 'description' => 'Dynamic server', ]); $reservationId = $this->insertReservation( serviceId: $service->id, + invoiceId: $invoice->id, userId: $service->user_id, guaranteedUntil: now()->subSecond() ); @@ -1719,7 +1729,7 @@ public function test_cron_can_suspend_a_confirmed_dynamic_service_through_coordi 'settings.cronjob_order_suspend' => 2, 'settings.cronjob_invoice' => 7, ]); - $service = $this->makeService(status: Service::STATUS_ACTIVE); + $service = $this->makeBillableService(Service::STATUS_ACTIVE); DB::table('services')->where('id', $service->id)->update([ 'expires_at' => now()->subDays(3), 'price' => 10, @@ -1742,7 +1752,7 @@ public function test_cron_can_suspend_a_confirmed_dynamic_service_through_coordi public function test_paid_renewal_can_reactivate_confirmed_dynamic_service(): void { Queue::fake(); - $service = $this->makeService(status: Service::STATUS_SUSPENDED); + $service = $this->makeBillableService(Service::STATUS_SUSPENDED); $this->insertReservation( serviceId: $service->id, userId: $service->user_id, @@ -2041,6 +2051,27 @@ private function makeService(string $status = 'pending'): Service return Service::query()->findOrFail($id); } + private function makeBillableService(string $status): Service + { + $product = $this->pterodactylProduct(); + $plan = Plan::factory()->create([ + 'priceable_id' => $product->id, + 'priceable_type' => Product::class, + 'type' => 'recurring', + 'billing_unit' => 'month', + 'billing_period' => 1, + ]); + $service = $this->makeService($status); + DB::table('services') + ->where('id', $service->id) + ->update([ + 'product_id' => $product->id, + 'plan_id' => $plan->id, + ]); + + return $service->fresh(); + } + /** * @return array{Service, Product} */ @@ -2133,6 +2164,16 @@ private function insertReservation( ? (string) User::query()->whereKey($userId)->value('email') : null, ], + 'allocation_requirements' => [ + 'required_count' => 1, + 'mappings' => [[ + 'environment_key' => 'SERVER_PORT', + 'requested_port' => null, + 'is_primary' => true, + ]], + 'allowed_port_ranges' => [], + 'dedicated_ip' => false, + ], 'allocations' => [[ 'allocation_id' => 7001, 'ip' => '192.0.2.10', diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index 759244d..c747182 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -2,6 +2,7 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; +use App\Models\User; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\DB; use Mockery; @@ -275,7 +276,9 @@ public function test_upgrade_holds_count_only_positive_reserved_deltas(): void public function test_confirmed_checkout_stays_overlaid_until_same_snapshot_proves_target(): void { $this->createCpuPolicy(); - $serviceRecord = \App\Models\Service::factory()->create(); + $serviceRecord = \App\Models\Service::factory()->create([ + 'user_id' => User::factory()->create()->id, + ]); DB::table('services')->where('id', $serviceRecord->id)->update([ 'status' => \App\Models\Service::STATUS_ACTIVE, ]); @@ -322,7 +325,9 @@ public function test_confirmed_checkout_stays_overlaid_until_same_snapshot_prove public function test_confirmed_upgrade_supersedes_checkout_and_overlays_only_snapshot_deficit(): void { $this->createCpuPolicy(); - $serviceRecord = \App\Models\Service::factory()->create(); + $serviceRecord = \App\Models\Service::factory()->create([ + 'user_id' => User::factory()->create()->id, + ]); DB::table('services')->where('id', $serviceRecord->id)->update([ 'status' => \App\Models\Service::STATUS_ACTIVE, ]); @@ -396,7 +401,9 @@ public function test_confirmed_upgrade_supersedes_checkout_and_overlays_only_sna public function test_multiple_confirmed_upgrades_keep_only_latest_target(): void { $this->createCpuPolicy(); - $serviceRecord = \App\Models\Service::factory()->create(); + $serviceRecord = \App\Models\Service::factory()->create([ + 'user_id' => User::factory()->create()->id, + ]); DB::table('services')->where('id', $serviceRecord->id)->update([ 'status' => \App\Models\Service::STATUS_ACTIVE, ]); @@ -469,7 +476,9 @@ public function test_multiple_confirmed_upgrades_keep_only_latest_target(): void public function test_conflicting_confirmed_server_identities_fail_snapshot_proof_closed(): void { $this->createCpuPolicy(); - $serviceRecord = \App\Models\Service::factory()->create(); + $serviceRecord = \App\Models\Service::factory()->create([ + 'user_id' => User::factory()->create()->id, + ]); DB::table('services')->where('id', $serviceRecord->id)->update([ 'status' => \App\Models\Service::STATUS_ACTIVE, ]); @@ -548,7 +557,9 @@ public function test_server_assignment_wins_over_stale_node_allocation_snapshot( public function test_confirmed_local_claim_blocks_a_stale_free_allocation_snapshot(): void { $this->createCpuPolicy(); - $serviceRecord = \App\Models\Service::factory()->create(); + $serviceRecord = \App\Models\Service::factory()->create([ + 'user_id' => User::factory()->create()->id, + ]); DB::table('services')->where('id', $serviceRecord->id)->update([ 'status' => \App\Models\Service::STATUS_ACTIVE, ]); @@ -706,7 +717,9 @@ public function test_pending_dedicated_hold_removes_its_whole_ip_from_all_stock( public function test_confirmed_dedicated_server_blocks_ip_until_service_is_cancelled(): void { $this->createCpuPolicy(); - $serviceRecord = \App\Models\Service::factory()->create(); + $serviceRecord = \App\Models\Service::factory()->create([ + 'user_id' => User::factory()->create()->id, + ]); DB::table('services')->where('id', $serviceRecord->id)->update([ 'status' => \App\Models\Service::STATUS_ACTIVE, ]); diff --git a/tests/Unit/ResourceQuoteServiceTest.php b/tests/Unit/ResourceQuoteServiceTest.php index d847cb4..37515c0 100644 --- a/tests/Unit/ResourceQuoteServiceTest.php +++ b/tests/Unit/ResourceQuoteServiceTest.php @@ -4,6 +4,7 @@ use App\Models\Product; use Mockery; +use PHPUnit\Framework\Attributes\DataProvider; use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException; use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\StockUnavailableException; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AllocationSelectionService; @@ -158,9 +159,7 @@ public function test_customer_quote_contains_no_node_identity(): void $this->assertStringNotContainsString('available_allocations', $encoded); } - /** - * @dataProvider unboundedInventoryReasons - */ + #[DataProvider('unboundedInventoryReasons')] public function test_unbounded_inventory_is_configuration_failure(string $reason): void { $configuration = $this->configuration(); @@ -286,6 +285,11 @@ private function node( 'cpu' => $cpu, 'disk' => $disk, ], + 'total' => [ + 'memory' => $memory, + 'cpu' => $cpu, + 'disk' => $disk, + ], 'available_allocations' => $allocationCount === 0 ? [] : array_map( diff --git a/tests/Unit/UpgradeReservationServiceTest.php b/tests/Unit/UpgradeReservationServiceTest.php index 9bfc777..2f5cc64 100644 --- a/tests/Unit/UpgradeReservationServiceTest.php +++ b/tests/Unit/UpgradeReservationServiceTest.php @@ -614,64 +614,6 @@ private function fixture(): object 'currency_code' => 'USD', 'status' => Service::STATUS_ACTIVE, ]); - $options = [ - 'memory' => $this->option( - $product, - 'memory', - 1024, - 32768, - 1024, - 4096 - ), - 'cpu' => $this->option( - $product, - 'cpu', - 100, - 800, - 100, - 200 - ), - 'disk' => $this->option( - $product, - 'disk', - 10240, - 102400, - 10240, - 20480 - ), - ]; - foreach ([ - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 20480, - ] as $resource => $value) { - ServiceConfig::create([ - 'configurable_id' => $service->id, - 'configurable_type' => Service::class, - 'config_option_id' => $options[$resource]->id, - 'config_value_id' => null, - 'slider_value' => $value, - ]); - } - $select = ConfigOption::create([ - 'name' => 'Template', - 'env_variable' => 'template', - 'type' => 'select', - 'hidden' => false, - 'upgradable' => true, - ]); - ConfigOptionProduct::create([ - 'product_id' => $product->id, - 'config_option_id' => $select->id, - ]); - $selectChild = ConfigOption::create([ - 'name' => 'Default', - 'env_variable' => 'default', - 'type' => 'option', - 'hidden' => false, - 'parent_id' => $select->id, - ]); - $panelIdentity = hash('sha256', 'https://panel.example'); $checkoutEmail = strtolower((string) $user->email); $checkoutPayload = [ @@ -685,6 +627,16 @@ private function fixture(): object 'cpu' => 200, 'disk' => 20480, ], + 'allocation_requirements' => [ + 'required_count' => 1, + 'mappings' => [[ + 'environment_key' => 'SERVER_PORT', + 'requested_port' => null, + 'is_primary' => true, + ]], + 'allowed_port_ranges' => [], + 'dedicated_ip' => false, + ], 'provisioning_identity' => [ 'nest_id' => 1, 'egg_id' => 2, @@ -735,6 +687,63 @@ private function fixture(): object 'created_at' => now(), 'updated_at' => now(), ]); + $options = [ + 'memory' => $this->option( + $product, + 'memory', + 1024, + 32768, + 1024, + 4096 + ), + 'cpu' => $this->option( + $product, + 'cpu', + 100, + 800, + 100, + 200 + ), + 'disk' => $this->option( + $product, + 'disk', + 10240, + 102400, + 10240, + 20480 + ), + ]; + foreach ([ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + ] as $resource => $value) { + ServiceConfig::create([ + 'configurable_id' => $service->id, + 'configurable_type' => Service::class, + 'config_option_id' => $options[$resource]->id, + 'config_value_id' => null, + 'slider_value' => $value, + ]); + } + $select = ConfigOption::create([ + 'name' => 'Template', + 'env_variable' => 'template', + 'type' => 'select', + 'hidden' => false, + 'upgradable' => true, + ]); + ConfigOptionProduct::create([ + 'product_id' => $product->id, + 'config_option_id' => $select->id, + ]); + $selectChild = ConfigOption::create([ + 'name' => 'Default', + 'env_variable' => 'default', + 'type' => 'option', + 'hidden' => false, + 'parent_id' => $select->id, + ]); $remote = (object) ['server' => [ 'id' => 99, From accb964e3b0ff810ff43c58a3897f7d2b870b19a Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 07:53:09 +1000 Subject: [PATCH 39/95] test: exercise guarded fulfillment contracts --- .../LegacyReservationReadinessTest.php | 2 +- tests/Feature/ResourceQuoteApiTest.php | 6 ++-- .../ReservationConfigurationServiceTest.php | 24 ++++++++++++-- tests/Unit/UpgradeReservationServiceTest.php | 32 +++++++++++-------- 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/tests/Feature/LegacyReservationReadinessTest.php b/tests/Feature/LegacyReservationReadinessTest.php index cfacc40..56c1423 100644 --- a/tests/Feature/LegacyReservationReadinessTest.php +++ b/tests/Feature/LegacyReservationReadinessTest.php @@ -49,7 +49,7 @@ public function test_confirmed_legacy_checkout_reports_actionable_identity_field $exception->getMessage() ); $this->assertStringContainsString( - 'never infer them', + 'never infer authority', $exception->getMessage() ); } diff --git a/tests/Feature/ResourceQuoteApiTest.php b/tests/Feature/ResourceQuoteApiTest.php index 6ecca23..4e4b045 100644 --- a/tests/Feature/ResourceQuoteApiTest.php +++ b/tests/Feature/ResourceQuoteApiTest.php @@ -179,7 +179,8 @@ public function test_owned_cart_item_quote_excludes_its_current_hold(): void ]); $this->app->instance(ResourceQuoteService::class, $quotes); - $this->withCookie('cart', $cart->ulid) + $this->withCredentials() + ->withCookie('cart', $cart->ulid) ->postJson( "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", ['config_options' => [], 'cart_item_id' => $cartItemId] @@ -203,7 +204,8 @@ public function test_cart_item_from_another_cart_cannot_be_used_for_exclusion(): 'updated_at' => now(), ]); - $this->withCookie('cart', $ownedCart->ulid) + $this->withCredentials() + ->withCookie('cart', $ownedCart->ulid) ->postJson( "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", ['config_options' => [], 'cart_item_id' => $otherItemId] diff --git a/tests/Unit/ReservationConfigurationServiceTest.php b/tests/Unit/ReservationConfigurationServiceTest.php index e809b04..6d62552 100644 --- a/tests/Unit/ReservationConfigurationServiceTest.php +++ b/tests/Unit/ReservationConfigurationServiceTest.php @@ -75,10 +75,26 @@ public function test_resource_or_node_change_changes_fingerprint(): void 'currency_code' => 'AUD', 'location_id' => 2, 'resources' => ['memory' => 4096, 'cpu' => 200, 'disk' => 51200], - 'calculated_price' => 25.00, + 'calculated_price' => '25.00', 'pricing_version' => str_repeat('a', 64), 'formula_version' => ReservationConfigurationService::FORMULA_VERSION, 'config_options' => [], + 'allocation_requirements' => [ + 'required_count' => 1, + 'mappings' => [[ + 'environment_key' => 'SERVER_PORT', + 'requested_port' => null, + 'is_primary' => true, + ]], + 'allowed_port_ranges' => [], + 'dedicated_ip' => false, + ], + 'provisioning_identity' => [ + 'nest_id' => 1, + 'egg_id' => 2, + 'user_external_id' => 'paymenter-user-30', + 'user_email' => 'customer@example.com', + ], ]; $original = $service->fingerprint($service->withNode($snapshot, 3)); @@ -95,7 +111,11 @@ public function test_resource_or_node_change_changes_fingerprint(): void $service->fingerprint($service->withNode($snapshot, 4)) ); - $guestPayload = $service->withNode(array_replace($snapshot, ['customer_id' => null]), 3); + $guestSnapshot = $snapshot; + $guestSnapshot['customer_id'] = null; + $guestSnapshot['provisioning_identity']['user_external_id'] = null; + $guestSnapshot['provisioning_identity']['user_email'] = null; + $guestPayload = $service->withNode($guestSnapshot, 3); $this->assertNotSame( $service->fingerprint($guestPayload), $service->fingerprint($service->withCustomer( diff --git a/tests/Unit/UpgradeReservationServiceTest.php b/tests/Unit/UpgradeReservationServiceTest.php index 2f5cc64..94e2ba7 100644 --- a/tests/Unit/UpgradeReservationServiceTest.php +++ b/tests/Unit/UpgradeReservationServiceTest.php @@ -18,6 +18,7 @@ use App\Models\ServiceUpgrade; use App\Models\Server; use App\Models\User; +use App\Services\Service\FulfillmentStatusTransitionService; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Queue; @@ -713,19 +714,24 @@ private function fixture(): object 20480 ), ]; - foreach ([ - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 20480, - ] as $resource => $value) { - ServiceConfig::create([ - 'configurable_id' => $service->id, - 'configurable_type' => Service::class, - 'config_option_id' => $options[$resource]->id, - 'config_value_id' => null, - 'slider_value' => $value, - ]); - } + FulfillmentStatusTransitionService::run( + $service, + function () use ($service, $options): void { + foreach ([ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + ] as $resource => $value) { + ServiceConfig::create([ + 'configurable_id' => $service->id, + 'configurable_type' => Service::class, + 'config_option_id' => $options[$resource]->id, + 'config_value_id' => null, + 'slider_value' => $value, + ]); + } + } + ); $select = ConfigOption::create([ 'name' => 'Template', 'env_variable' => 'template', From c8439a29ec6ead265ae135d9915b308f8c95078e Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 07:55:44 +1000 Subject: [PATCH 40/95] fix: persist authoritative upgrade placement --- Services/UpgradeReservationService.php | 2 ++ tests/Unit/UpgradeReservationServiceTest.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Services/UpgradeReservationService.php b/Services/UpgradeReservationService.php index eb53a44..b8ff9e9 100644 --- a/Services/UpgradeReservationService.php +++ b/Services/UpgradeReservationService.php @@ -136,6 +136,8 @@ public function reserveForUpgrade( 'cart_id' => null, 'server_extension_id' => $upgrade->product->server_id, 'panel_identity' => $context['panel_identity'], + 'node_id' => $context['node_id'], + 'location_id' => $context['location_id'], 'service_id' => $upgrade->service_id, 'service_upgrade_id' => $upgrade->id, 'upgrade_guard_id' => $upgrade->id, diff --git a/tests/Unit/UpgradeReservationServiceTest.php b/tests/Unit/UpgradeReservationServiceTest.php index 94e2ba7..8f01e28 100644 --- a/tests/Unit/UpgradeReservationServiceTest.php +++ b/tests/Unit/UpgradeReservationServiceTest.php @@ -158,6 +158,8 @@ public function test_upgrade_reserves_only_positive_delta_but_keeps_full_target( $this->assertSame(4096, (int) $reservation->reserved_memory); $this->assertSame(0, (int) $reservation->reserved_cpu); $this->assertSame(10240, (int) $reservation->reserved_disk); + $this->assertSame(1, (int) $reservation->node_id); + $this->assertSame(1, (int) $reservation->location_id); $this->assertSame(99, (int) $reservation->external_server_id); $this->assertSame(44, (int) $reservation->external_user_id); $this->assertSame( From 2c05d46f5ea7aebcdd0b151adf6b530e59592cee Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 08:25:14 +1000 Subject: [PATCH 41/95] fix: preserve reservation fingerprint round trips --- Services/ReservationConfigurationService.php | 12 + .../ReservationConfigurationServiceTest.php | 24 + tests/Unit/UpgradeReservationServiceTest.php | 461 +++++++++++++----- 3 files changed, 384 insertions(+), 113 deletions(-) diff --git a/Services/ReservationConfigurationService.php b/Services/ReservationConfigurationService.php index 99d2d36..3229f41 100644 --- a/Services/ReservationConfigurationService.php +++ b/Services/ReservationConfigurationService.php @@ -542,6 +542,18 @@ private function canonicalize(array $value): array foreach ($value as $key => $item) { if (is_array($item)) { $value[$key] = $this->canonicalize($item); + } elseif ( + is_float($item) + && is_finite($item) + && floor($item) === $item + && $item >= PHP_INT_MIN + && $item <= PHP_INT_MAX + ) { + // JSON columns may normalize 4096.0 to 4096. Treat integral + // numeric values identically before both persistence and + // fingerprinting so a database round trip cannot invalidate + // an otherwise immutable reservation. + $value[$key] = (int) $item; } } diff --git a/tests/Unit/ReservationConfigurationServiceTest.php b/tests/Unit/ReservationConfigurationServiceTest.php index 6d62552..d86a88f 100644 --- a/tests/Unit/ReservationConfigurationServiceTest.php +++ b/tests/Unit/ReservationConfigurationServiceTest.php @@ -61,6 +61,30 @@ public function test_fingerprint_is_stable_for_equivalent_key_order(): void $this->assertSame($service->fingerprint($left), $service->fingerprint($right)); } + public function test_integral_float_fingerprint_survives_json_round_trip(): void + { + $service = new ReservationConfigurationService; + $payload = [ + 'config_options' => [ + ['id' => 1, 'value' => 4096.0], + ['id' => 2, 'value' => 1.5], + ], + ]; + $stored = json_encode($payload, JSON_THROW_ON_ERROR); + $reloaded = json_decode( + $stored, + true, + 512, + JSON_THROW_ON_ERROR + ); + + $this->assertStringNotContainsString('4096.0', $stored); + $this->assertSame( + $service->fingerprint($payload), + $service->fingerprint($reloaded) + ); + } + public function test_resource_or_node_change_changes_fingerprint(): void { $service = new ReservationConfigurationService; diff --git a/tests/Unit/UpgradeReservationServiceTest.php b/tests/Unit/UpgradeReservationServiceTest.php index 8f01e28..c6edd5d 100644 --- a/tests/Unit/UpgradeReservationServiceTest.php +++ b/tests/Unit/UpgradeReservationServiceTest.php @@ -6,6 +6,7 @@ use App\Exceptions\PermanentProvisioningException; use App\Helpers\ExtensionHelper; use App\Jobs\Server\UpgradeJob; +use App\Models\Cart; use App\Models\ConfigOption; use App\Models\ConfigOptionProduct; use App\Models\Invoice; @@ -18,7 +19,7 @@ use App\Models\ServiceUpgrade; use App\Models\Server; use App\Models\User; -use App\Services\Service\FulfillmentStatusTransitionService; +use App\Services\Service\CapacityServiceCreationCoordinator; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Queue; @@ -87,6 +88,72 @@ protected function tearDown(): void parent::tearDown(); } + public function test_upgrade_fixture_starts_from_completed_paid_checkout(): void + { + $fixture = $this->fixture(); + $reservation = DB::table('ptero_resource_reservations') + ->where('id', $fixture->checkoutReservationId) + ->first(); + $allocation = DB::table('ptero_reservation_allocations') + ->where('reservation_id', $fixture->checkoutReservationId) + ->first(); + $invoice = $fixture->checkoutInvoice->fresh(); + $payload = json_decode( + (string) $reservation->configuration_payload, + true, + 512, + JSON_THROW_ON_ERROR + ); + + $this->assertSame('checkout', $reservation->purpose); + $this->assertSame('confirmed', $reservation->status); + $this->assertNull($reservation->cart_item_id); + $this->assertSame( + $fixture->cartItemGuardId, + (int) $reservation->cart_item_guard_id + ); + $this->assertFalse( + DB::table('carts') + ->where('id', $reservation->cart_id) + ->exists() + ); + $this->assertSame(0, (int) $reservation->reserved_memory); + $this->assertSame(0, (int) $reservation->reserved_cpu); + $this->assertSame(0, (int) $reservation->reserved_disk); + $this->assertSame(1, (int) $reservation->provisioning_attempts); + $this->assertNotNull($reservation->paid_committed_at); + $this->assertNotNull($reservation->last_provisioning_attempt_at); + $this->assertNotNull($reservation->consumed_at); + $this->assertNotNull($reservation->last_reconciled_at); + $this->assertNotNull($allocation->released_at); + $this->assertSame(Invoice::STATUS_PAID, $invoice->status); + $this->assertSame( + $invoice->due_at->getTimestamp(), + \Carbon\Carbon::parse( + $reservation->guaranteed_until + )->getTimestamp() + ); + $this->assertSame( + $fixture->checkoutPrice, + (string) $invoice->items()->sole()->price + ); + $this->assertSame( + (int) $fixture->select->id, + collect($payload['config_options']) + ->firstWhere('environment_key', 'template')['id'] + ); + $this->assertSame( + (new ReservationConfigurationService)->fingerprint([ + 'product_id' => (int) $fixture->product->id, + 'plan_id' => (int) $fixture->plan->id, + 'currency_code' => 'USD', + 'calculated_price' => $fixture->checkoutPrice, + 'config_options' => $payload['config_options'], + ]), + $reservation->pricing_version + ); + } + public function test_fixed_node_quote_clamps_32_gb_to_23_gb_and_accepts_select_key(): void { $fixture = $this->fixture(); @@ -131,13 +198,20 @@ public function test_duplicate_active_resource_slider_fails_closed_but_hidden_on ); } - $duplicate->hidden = true; - $duplicate->save(); - $fixture->service->unsetRelation('product'); + $hiddenFixture = $this->fixture(); + $this->option( + $hiddenFixture->product, + 'memory', + 1024, + 32768, + 1024, + 4096, + hidden: true + ); - $quote = $fixture->upgrades->quoteForService( - $fixture->service, - $this->selection($fixture) + $quote = $hiddenFixture->upgrades->quoteForService( + $hiddenFixture->service, + $this->selection($hiddenFixture) ); $this->assertSame(23552, $quote['bounds']['memory']['max']); } @@ -359,7 +433,7 @@ public function test_paid_upgrade_payload_is_verified_before_leasing(): void $payload = (array) $reservation->fresh()->configuration_payload; $payload['target']['memory'] = 16384; DB::table('ptero_resource_reservations') - ->whereKey($reservation->id) + ->where('id', $reservation->id) ->update([ 'configuration_payload' => json_encode( $payload, @@ -395,7 +469,7 @@ public function test_tampered_upgrade_payload_is_rejected_before_payment(): void $payload = (array) $reservation->configuration_payload; $payload['target']['memory'] = 16384; DB::table('ptero_resource_reservations') - ->whereKey($reservation->id) + ->where('id', $reservation->id) ->update([ 'configuration_payload' => json_encode( $payload, @@ -428,7 +502,9 @@ public function test_tampered_invoice_line_is_cancelled_before_paid_transition() $upgrade, $invoice->due_at ); - $invoice->items()->firstOrFail()->update(['price' => 1]); + DB::table('invoice_items') + ->where('id', $invoice->items()->firstOrFail()->id) + ->update(['price' => 1]); $failure = $fixture->upgrades->preflightPaidUpgrade( $upgrade, @@ -489,13 +565,18 @@ public function test_add_payment_preserves_rejected_upgrade_attention_and_paymen $invoice->due_at ); - // Simulate renewal/admin drift beneath the model guard so the real - // synchronous payment listener encounters a stale immutable source. - DB::table('services') - ->where('id', $fixture->service->id) + // Simulate storage tampering beneath the model layer so the real + // synchronous payment listener must preserve external payment + // evidence without consuming an invalid capacity commitment. + $payload = (array) $reservation->configuration_payload; + $payload['target']['memory'] = 16384; + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) ->update([ - 'price' => '11.00', - 'updated_at' => now(), + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), ]); ExtensionHelper::addPayment( @@ -606,30 +687,209 @@ private function fixture(): object 'currency_code' => 'USD', ]); - // Create the service while the product is still non-dynamic; the - // production checkout creates dynamic services through its coordinator. - $service = Service::factory()->create([ + $options = [ + 'memory' => $this->option( + $product, + 'memory', + 1024, + 32768, + 1024, + 4096 + ), + 'cpu' => $this->option( + $product, + 'cpu', + 100, + 800, + 100, + 200 + ), + 'disk' => $this->option( + $product, + 'disk', + 10240, + 102400, + 10240, + 20480 + ), + ]; + $select = ConfigOption::create([ + 'name' => 'Template', + 'env_variable' => 'template', + 'type' => 'select', + 'hidden' => false, + 'upgradable' => true, + ]); + ConfigOptionProduct::create([ + 'product_id' => $product->id, + 'config_option_id' => $select->id, + ]); + $selectChild = ConfigOption::create([ + 'name' => 'Default', + 'env_variable' => 'default', + 'type' => 'option', + 'hidden' => false, + 'parent_id' => $select->id, + ]); + + $resourceValues = [ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + ]; + $checkoutPrice = number_format( + 10 + array_sum($resourceValues), + 2, + '.', + '' + ); + $checkoutStartedAt = now()->subMinutes(4); + $checkoutCommittedAt = now()->subMinutes(3); + $checkoutCompletedAt = now()->subMinutes(2); + $checkoutDueAt = now()->addDays(7); + $service = CapacityServiceCreationCoordinator::run( + fn () => Service::factory()->create([ + 'user_id' => $user->id, + 'product_id' => $product->id, + 'plan_id' => $plan->id, + 'quantity' => 1, + 'price' => $checkoutPrice, + 'currency_code' => 'USD', + 'status' => Service::STATUS_ACTIVE, + 'expires_at' => now()->addMonth(), + ]) + ); + foreach ($resourceValues as $resource => $value) { + ServiceConfig::create([ + 'configurable_id' => $service->id, + 'configurable_type' => Service::class, + 'config_option_id' => $options[$resource]->id, + 'config_value_id' => null, + 'slider_value' => $value, + ]); + } + ServiceConfig::create([ + 'configurable_id' => $service->id, + 'configurable_type' => Service::class, + 'config_option_id' => $select->id, + 'config_value_id' => $selectChild->id, + 'slider_value' => null, + ]); + + $cart = Cart::create([ 'user_id' => $user->id, + 'currency_code' => 'USD', + ]); + $panelIdentity = hash('sha256', 'https://panel.example'); + $checkoutEmail = strtolower((string) $user->email); + $allocationId = 1000 + (int) $service->id; + $allocationIp = '192.0.2.'.(((int) $service->id % 250) + 1); + $allocationPort = 20000 + ((int) $service->id % 40000); + $configurationOptions = collect($resourceValues) + ->map(function (int $value, string $resource) use ($options): array { + $option = $options[$resource]; + + return [ + 'id' => (int) $option->id, + 'type' => 'dynamic_slider', + 'environment_key' => $resource, + 'resource_type' => $resource, + 'value' => (float) $value, + 'metadata' => (array) $option->metadata, + ]; + }) + ->sortBy('id') + ->values() + ->all(); + $configurationOptions[] = [ + 'id' => (int) $select->id, + 'type' => 'select', + 'environment_key' => 'template', + 'resource_type' => null, + 'value' => (float) $selectChild->id, + 'metadata' => (array) ($select->metadata ?? []), + ]; + usort( + $configurationOptions, + fn (array $left, array $right): int => + $left['id'] <=> $right['id'] + ); + $cartSelections = collect($configurationOptions) + ->map(function (array $option) use ( + $options, + $select + ): array { + $model = $option['type'] === 'dynamic_slider' + ? $options[$option['resource_type']] + : $select; + + return [ + 'option_id' => (int) $option['id'], + 'option_name' => (string) $model->name, + 'option_type' => (string) $option['type'], + 'option_env_variable' => + (string) $option['environment_key'], + 'value' => $option['value'], + ]; + }) + ->all(); + $cartItemGuardId = DB::table('cart_items')->insertGetId([ + 'cart_id' => $cart->id, 'product_id' => $product->id, 'plan_id' => $plan->id, + 'config_options' => json_encode( + $cartSelections, + JSON_THROW_ON_ERROR + ), + 'checkout_config' => json_encode([], JSON_THROW_ON_ERROR), 'quantity' => 1, - 'price' => 10, + 'created_at' => $checkoutStartedAt, + 'updated_at' => $checkoutStartedAt, + ]); + $checkoutInvoice = Invoice::factory()->create([ + 'user_id' => $user->id, 'currency_code' => 'USD', - 'status' => Service::STATUS_ACTIVE, + 'status' => Invoice::STATUS_PENDING, + 'due_at' => $checkoutDueAt, ]); - $panelIdentity = hash('sha256', 'https://panel.example'); - $checkoutEmail = strtolower((string) $user->email); - $checkoutPayload = [ - 'customer_id' => (int) $user->id, + $checkoutInvoice->items()->create([ + 'description' => (string) $service->description, + 'price' => $checkoutPrice, + 'quantity' => 1, + 'reference_id' => $service->id, + 'reference_type' => Service::class, + ]); + DB::table('invoices') + ->where('id', $checkoutInvoice->id) + ->update([ + 'status' => Invoice::STATUS_PAID, + 'updated_at' => $checkoutCommittedAt, + ]); + $checkoutInvoice->refresh(); + $checkoutConfiguration = new ReservationConfigurationService; + $pricingVersion = $checkoutConfiguration->fingerprint([ 'product_id' => (int) $product->id, 'plan_id' => (int) $plan->id, + 'currency_code' => 'USD', + 'calculated_price' => $checkoutPrice, + 'config_options' => $configurationOptions, + ]); + $checkoutPayload = $checkoutConfiguration->withPlacement([ + 'customer_id' => (int) $user->id, + 'cart_id' => (int) $cart->id, + 'server_extension_id' => (int) $server->id, 'panel_identity' => $panelIdentity, - 'node_id' => 1, - 'resources' => [ - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 20480, - ], + 'product_id' => (int) $product->id, + 'plan_id' => (int) $plan->id, + 'quantity' => 1, + 'currency_code' => 'USD', + 'location_id' => 1, + 'resources' => $resourceValues, + 'calculated_price' => $checkoutPrice, + 'pricing_version' => $pricingVersion, + 'formula_version' => + ReservationConfigurationService::FORMULA_VERSION, + 'config_options' => $configurationOptions, 'allocation_requirements' => [ 'required_count' => 1, 'mappings' => [[ @@ -646,27 +906,42 @@ private function fixture(): object 'user_external_id' => "paymenter-user-{$user->id}", 'user_email' => $checkoutEmail, ], - ]; - $checkoutConfiguration = new ReservationConfigurationService; - DB::table('ptero_resource_reservations')->insert([ + ], 1, [[ + 'allocation_id' => $allocationId, + 'ip' => $allocationIp, + 'port' => $allocationPort, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ]]); + $checkoutReservationId = DB::table( + 'ptero_resource_reservations' + )->insertGetId([ 'purpose' => 'checkout', 'token' => hash('sha256', "checkout:{$service->id}"), + 'cart_item_id' => $cartItemGuardId, + 'cart_item_guard_id' => $cartItemGuardId, + 'cart_id' => $cart->id, + 'server_extension_id' => $server->id, 'service_id' => $service->id, 'service_guard_id' => $service->id, + 'invoice_id' => $checkoutInvoice->id, 'user_id' => $user->id, 'node_id' => 1, 'location_id' => 1, 'memory' => 4096, 'cpu' => 200, 'disk' => 20480, - 'reserved_memory' => 4096, - 'reserved_cpu' => 200, - 'reserved_disk' => 20480, - 'calculated_price' => 10, + 'reserved_memory' => 0, + 'reserved_cpu' => 0, + 'reserved_disk' => 0, + 'calculated_price' => $checkoutPrice, 'pricing_breakdown' => json_encode([], JSON_THROW_ON_ERROR), 'status' => 'confirmed', - 'expires_at' => now()->addDays(30), - 'guaranteed_until' => now()->addDays(30), + 'expires_at' => $checkoutDueAt, + 'guaranteed_until' => $checkoutDueAt, + 'paid_committed_at' => $checkoutCommittedAt, + 'provisioning_attempts' => 1, + 'last_provisioning_attempt_at' => $checkoutCommittedAt, 'panel_identity' => $panelIdentity, 'product_id' => $product->id, 'plan_id' => $plan->id, @@ -678,7 +953,7 @@ private function fixture(): object $checkoutPayload, JSON_THROW_ON_ERROR ), - 'pricing_version' => str_repeat('a', 64), + 'pricing_version' => $pricingVersion, 'formula_version' => ReservationConfigurationService::FORMULA_VERSION, 'external_server_id' => 99, @@ -686,72 +961,25 @@ private function fixture(): object 'external_server_uuid' => '10000000-0000-4000-8000-000000000099', 'external_server_identifier' => 'server-99', - 'consumed_at' => now(), - 'created_at' => now(), - 'updated_at' => now(), + 'last_reconciled_at' => $checkoutCompletedAt, + 'consumed_at' => $checkoutCompletedAt, + 'created_at' => $checkoutStartedAt, + 'updated_at' => $checkoutCompletedAt, ]); - $options = [ - 'memory' => $this->option( - $product, - 'memory', - 1024, - 32768, - 1024, - 4096 - ), - 'cpu' => $this->option( - $product, - 'cpu', - 100, - 800, - 100, - 200 - ), - 'disk' => $this->option( - $product, - 'disk', - 10240, - 102400, - 10240, - 20480 - ), - ]; - FulfillmentStatusTransitionService::run( - $service, - function () use ($service, $options): void { - foreach ([ - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 20480, - ] as $resource => $value) { - ServiceConfig::create([ - 'configurable_id' => $service->id, - 'configurable_type' => Service::class, - 'config_option_id' => $options[$resource]->id, - 'config_value_id' => null, - 'slider_value' => $value, - ]); - } - } - ); - $select = ConfigOption::create([ - 'name' => 'Template', - 'env_variable' => 'template', - 'type' => 'select', - 'hidden' => false, - 'upgradable' => true, - ]); - ConfigOptionProduct::create([ - 'product_id' => $product->id, - 'config_option_id' => $select->id, - ]); - $selectChild = ConfigOption::create([ - 'name' => 'Default', - 'env_variable' => 'default', - 'type' => 'option', - 'hidden' => false, - 'parent_id' => $select->id, + DB::table('ptero_reservation_allocations')->insert([ + 'reservation_id' => $checkoutReservationId, + 'panel_identity' => $panelIdentity, + 'node_id' => 1, + 'allocation_id' => $allocationId, + 'ip' => $allocationIp, + 'port' => $allocationPort, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + 'released_at' => $checkoutCompletedAt, + 'created_at' => $checkoutStartedAt, + 'updated_at' => $checkoutCompletedAt, ]); + DB::table('carts')->where('id', $cart->id)->delete(); $remote = (object) ['server' => [ 'id' => 99, @@ -773,8 +1001,8 @@ function () use ($service, $options): void { 'database_limit' => 2, 'allocation_limit' => 0, 'backup_limit' => 3, - 'allocation' => 123, - 'assigned_allocation_ids' => [123], + 'allocation' => $allocationId, + 'assigned_allocation_ids' => [$allocationId], ]]; $inventory = Mockery::mock(PterodactylInventoryService::class); $inventory->shouldReceive('assertExclusiveProvisioningControl') @@ -805,6 +1033,11 @@ function () use ($service, $options): void { $resources->shouldReceive('verifyNodeCapacity') ->zeroOrMoreTimes() ->andReturn(true); + $upgrades = new UpgradeReservationService( + $inventory, + $resources + ); + $this->app->instance(UpgradeReservationService::class, $upgrades); return (object) [ 'user' => $user, @@ -816,10 +1049,11 @@ function () use ($service, $options): void { 'select' => $select, 'selectChild' => $selectChild, 'remote' => $remote, - 'upgrades' => new UpgradeReservationService( - $inventory, - $resources - ), + 'upgrades' => $upgrades, + 'checkoutReservationId' => $checkoutReservationId, + 'checkoutInvoice' => $checkoutInvoice, + 'checkoutPrice' => $checkoutPrice, + 'cartItemGuardId' => $cartItemGuardId, ]; } @@ -901,13 +1135,14 @@ private function option( int $min, int $max, int $step, - int $default + int $default, + bool $hidden = false ): ConfigOption { $option = ConfigOption::create([ 'name' => ucfirst($resource), 'env_variable' => $resource, 'type' => 'dynamic_slider', - 'hidden' => false, + 'hidden' => $hidden, 'upgradable' => true, 'metadata' => [ 'managed_by' => 'dynamic_pterodactyl', From a53c46e961b3b0d2eb6b53dc202728aec0f7ed5b Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 08:27:18 +1000 Subject: [PATCH 42/95] test: change non-resource upgrade selection --- tests/Unit/UpgradeReservationServiceTest.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/Unit/UpgradeReservationServiceTest.php b/tests/Unit/UpgradeReservationServiceTest.php index c6edd5d..0dc572d 100644 --- a/tests/Unit/UpgradeReservationServiceTest.php +++ b/tests/Unit/UpgradeReservationServiceTest.php @@ -361,7 +361,7 @@ public function test_dynamic_upgrade_rejects_non_resource_configuration_change() [$upgrade, $invoice] = $this->upgrade($fixture); $upgrade->configs()->create([ 'config_option_id' => $fixture->select->id, - 'config_value_id' => $fixture->selectChild->id, + 'config_value_id' => $fixture->selectAlternate->id, 'slider_value' => null, ]); $upgrade->unsetRelation('configs'); @@ -731,6 +731,13 @@ private function fixture(): object 'hidden' => false, 'parent_id' => $select->id, ]); + $selectAlternate = ConfigOption::create([ + 'name' => 'Alternate', + 'env_variable' => 'alternate', + 'type' => 'option', + 'hidden' => false, + 'parent_id' => $select->id, + ]); $resourceValues = [ 'memory' => 4096, @@ -1048,6 +1055,7 @@ private function fixture(): object 'options' => $options, 'select' => $select, 'selectChild' => $selectChild, + 'selectAlternate' => $selectAlternate, 'remote' => $remote, 'upgrades' => $upgrades, 'checkoutReservationId' => $checkoutReservationId, From 0998825a86d42f97f0532e93deee907e71fc69b2 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 11:46:29 +1000 Subject: [PATCH 43/95] fix: close stock inventory and fulfillment races --- Admin/Pages/SetupWizard.php | 18 +- DynamicPterodactyl.php | 18 + .../Api/ResourceQuoteController.php | 7 +- Services/ConfigOptionSetupService.php | 9 + Services/PterodactylInventoryService.php | 275 +- .../QuoteRateLimitConfigurationService.php | 104 + Services/QuoteRateLimiterService.php | 38 + Services/ReservationConfigurationService.php | 277 +- Services/ReservationService.php | 553 +++- Services/ResourceCalculationService.php | 465 +++- Services/UpgradeReservationService.php | 198 +- ...ce_one_checkout_commitment_per_service.php | 150 +- migration-readiness.php | 2422 ++++++++++++++++- routes/api.php | 12 +- .../LegacyReservationReadinessTest.php | 1592 ++++++++++- tests/Feature/ResourceQuoteApiTest.php | 143 + tests/Unit/ConfigOptionSetupServiceTest.php | 22 + .../Unit/PterodactylInventoryServiceTest.php | 477 +++- tests/Unit/QuoteRateLimiterServiceTest.php | 147 + tests/Unit/ReservationServiceTest.php | 363 ++- tests/Unit/ResourceCalculationServiceTest.php | 1004 +++++-- tests/Unit/UpgradeReservationServiceTest.php | 358 +++ 22 files changed, 7712 insertions(+), 940 deletions(-) create mode 100644 Services/QuoteRateLimitConfigurationService.php create mode 100644 Services/QuoteRateLimiterService.php create mode 100644 tests/Unit/QuoteRateLimiterServiceTest.php diff --git a/Admin/Pages/SetupWizard.php b/Admin/Pages/SetupWizard.php index f415121..2c47c28 100644 --- a/Admin/Pages/SetupWizard.php +++ b/Admin/Pages/SetupWizard.php @@ -157,14 +157,14 @@ public function form(Schema $schema): Schema ->suffix('GB') ->numeric() ->required() - ->minValue(0) + ->minValue(0.0001) ->default(1), TextInput::make('memory_max') ->label('Max') ->suffix('GB') ->numeric() ->required() - ->minValue(0) + ->minValue(0.0001) ->default(64), TextInput::make('memory_step') ->label('Step') @@ -178,7 +178,7 @@ public function form(Schema $schema): Schema ->suffix('GB') ->numeric() ->required() - ->minValue(0) + ->minValue(0.0001) ->default(4), ]), ]), @@ -198,14 +198,14 @@ public function form(Schema $schema): Schema ->suffix('cores') ->numeric() ->required() - ->minValue(0) + ->minValue(0.0001) ->default(1), TextInput::make('cpu_max') ->label('Max') ->suffix('cores') ->numeric() ->required() - ->minValue(0) + ->minValue(0.0001) ->default(8), TextInput::make('cpu_step') ->label('Step') @@ -218,7 +218,7 @@ public function form(Schema $schema): Schema ->suffix('cores') ->numeric() ->required() - ->minValue(0) + ->minValue(0.0001) ->default(2), ]), ]), @@ -238,14 +238,14 @@ public function form(Schema $schema): Schema ->suffix('GB') ->numeric() ->required() - ->minValue(0) + ->minValue(0.0001) ->default(10), TextInput::make('disk_max') ->label('Max') ->suffix('GB') ->numeric() ->required() - ->minValue(0) + ->minValue(0.0001) ->default(500), TextInput::make('disk_step') ->label('Step') @@ -259,7 +259,7 @@ public function form(Schema $schema): Schema ->suffix('GB') ->numeric() ->required() - ->minValue(0) + ->minValue(0.0001) ->default(50), ]), ]), diff --git a/DynamicPterodactyl.php b/DynamicPterodactyl.php index 2c0fa55..fba1d1a 100644 --- a/DynamicPterodactyl.php +++ b/DynamicPterodactyl.php @@ -18,6 +18,7 @@ use Paymenter\Extensions\Others\DynamicPterodactyl\Policies\ResourceReservationPolicy; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AlertService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\LegacyReservationReadinessService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\QuoteRateLimiterService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\UpgradeReservationService; @@ -71,6 +72,22 @@ public function getConfig($values = []): array 'default' => 15, 'validation' => 'integer|min:5|max:60', ], + [ + 'name' => 'quote_rate_limit_per_ip', + 'label' => 'Quote rate limit per customer IP', + 'type' => 'number', + 'description' => 'Maximum checkout and upgrade stock quotes accepted from one IP address per minute.', + 'default' => 10, + 'validation' => 'integer|min:1|max:60', + ], + [ + 'name' => 'quote_rate_limit_global', + 'label' => 'Global quote rate limit', + 'type' => 'number', + 'description' => 'Maximum checkout and upgrade stock quotes accepted for this Pterodactyl panel per minute across all customers.', + 'default' => 60, + 'validation' => 'integer|min:1|max:240', + ], [ 'name' => 'exclusive_provisioning_control', 'label' => 'Paymenter exclusively controls eligible nodes', @@ -126,6 +143,7 @@ public function uninstalled(): void public function boot(): void { Gate::policy(ResourceReservation::class, ResourceReservationPolicy::class); + app(QuoteRateLimiterService::class)->register(); // Register routes require __DIR__ . '/routes/api.php'; diff --git a/Http/Controllers/Api/ResourceQuoteController.php b/Http/Controllers/Api/ResourceQuoteController.php index 1813cb2..c16a5c8 100644 --- a/Http/Controllers/Api/ResourceQuoteController.php +++ b/Http/Controllers/Api/ResourceQuoteController.php @@ -104,7 +104,12 @@ private function excludedReservationToken( } return ResourceReservation::query() - ->pending() + // Stock accounting keeps an expired pending row authoritative + // until the cart mutation atomically retires it and releases its + // allocation claims. Let the owning cart exclude that same row + // while re-quoting so it can reach the cleanup/replacement + // transaction instead of deadlocking behind its own stale hold. + ->where('status', ResourceReservation::STATUS_PENDING) ->where('cart_item_id', $item->id) ->value('token'); } diff --git a/Services/ConfigOptionSetupService.php b/Services/ConfigOptionSetupService.php index 4be4320..ceb785f 100644 --- a/Services/ConfigOptionSetupService.php +++ b/Services/ConfigOptionSetupService.php @@ -188,6 +188,15 @@ private function buildResourceMetadata( 'pricing' => $pricing, ]; + // Pterodactyl interprets zero RAM, CPU, or disk as an unlimited + // resource. Dynamic stock must never allow a customer-selectable zero + // minimum to bypass the finite inventory contract. + if ($metadata['min'] <= 0) { + throw new \InvalidArgumentException( + ucfirst($resourceType).' minimum must be greater than zero.' + ); + } + $errors = []; (new DynamicSliderMetadataRule())->validate( 'metadata', diff --git a/Services/PterodactylInventoryService.php b/Services/PterodactylInventoryService.php index 31c7611..1eb79a6 100644 --- a/Services/PterodactylInventoryService.php +++ b/Services/PterodactylInventoryService.php @@ -10,6 +10,12 @@ class PterodactylInventoryService { + /** + * A corrupt or hostile paginator must not make inventory reads unbounded. + * At 100 resources per request this still permits a 10,000-row snapshot. + */ + private const MAX_PAGINATION_PAGES = 100; + private string $apiUrl; private string $apiKey; @@ -97,7 +103,7 @@ public function locations(): array } /** - * Pterodactyl 1.11 does not allow location_id as a NodeController filter. + * Pterodactyl does not allow location_id as a NodeController filter. * Read every page and apply the location constraint locally. * * @return list> @@ -130,7 +136,7 @@ public function nodes(): array if (! is_array($allocated)) { throw new \RuntimeException( 'Pterodactyl node inventory is missing allocated_resources. ' - .'Grant the application key node read permission and use Pterodactyl 1.11 or newer.' + .'Grant the application key node read permission and use Pterodactyl 1.12.3 or newer.' ); } @@ -233,14 +239,13 @@ public function serversForNodes(array $nodeIds): array $featureLimits['allocations'] ?? null, 'server.feature_limits.allocations' ); - $allocationResources = $resource['relationships']['allocations']['data'] - ?? null; - if (! is_array($allocationResources) || ! array_is_list($allocationResources)) { - throw new \RuntimeException( - 'Pterodactyl server inventory is missing the allocations relationship. ' - .'Grant the application key allocation read permission.' - ); - } + $allocationResources = $this->relationshipData( + $resource, + $attributes, + 'server', + 'allocations', + 'Grant the application key allocation read permission.' + ); $assignedAllocationIds = array_map(function (array $allocation): int { $allocationAttributes = $this->attributes($allocation, 'allocation'); @@ -367,14 +372,14 @@ public function availableAllocationsForNode(int $nodeId): array */ private function availableNodeAllocations(array $nodeResource): array { - $resources = $nodeResource['relationships']['allocations']['data'] - ?? null; - if (! is_array($resources) || ! array_is_list($resources)) { - throw new \RuntimeException( - 'Pterodactyl node inventory is missing the allocations relationship. ' - .'Grant the application key allocation read permission.' - ); - } + $attributes = $this->attributes($nodeResource, 'node'); + $resources = $this->relationshipData( + $nodeResource, + $attributes, + 'node', + 'allocations', + 'Grant the application key allocation read permission.' + ); $parsed = []; foreach ($resources as $resource) { @@ -514,14 +519,12 @@ public function serverByExternalId(int|string $externalId): array $attributes['allocation'] ?? null, 'server.allocation' ); - $allocationResources = $payload['relationships']['allocations']['data'] - ?? $attributes['relationships']['allocations']['data'] - ?? null; - if (! is_array($allocationResources) || ! array_is_list($allocationResources)) { - throw new \RuntimeException( - 'Pterodactyl server inventory is missing the allocations relationship.' - ); - } + $allocationResources = $this->relationshipData( + $payload, + $attributes, + 'server', + 'allocations' + ); $assignedAllocationIds = array_map(function (array $allocation): int { $allocationAttributes = $this->attributes($allocation, 'allocation'); @@ -669,8 +672,16 @@ private function paginated(string $path, array $query = []): array { $page = 1; $resources = []; + $resourceIdentities = []; + $paginationSnapshot = null; while (true) { + if ($page > self::MAX_PAGINATION_PAGES) { + throw new \RuntimeException( + 'Pterodactyl pagination exceeds the safe page limit.' + ); + } + $payload = $this->get($path, [ ...$query, 'page' => $page, @@ -682,15 +693,7 @@ private function paginated(string $path, array $query = []): array throw new \RuntimeException('Pterodactyl returned an invalid paginated resource payload.'); } - $resources = array_merge($resources, $data); $pagination = $payload['meta']['pagination'] ?? null; - - // Fractal includes pagination metadata. Accepting a missing block as - // one page also supports stock Pterodactyl's small relationship - // responses without silently skipping an advertised next page. - if ($pagination === null) { - break; - } if (! is_array($pagination)) { throw new \RuntimeException('Pterodactyl returned invalid pagination metadata.'); } @@ -699,24 +702,174 @@ private function paginated(string $path, array $query = []): array $pagination['current_page'] ?? null, 'pagination.current_page' ); - $totalPages = $this->nonNegativeInteger( - $pagination['total_pages'] ?? null, - 'pagination.total_pages' + $total = $this->nonNegativeInteger( + $pagination['total'] ?? null, + 'pagination.total' ); + $perPage = $this->positiveInteger( + $pagination['per_page'] ?? null, + 'pagination.per_page' + ); + $totalPages = $this->paginationLastPage($pagination); + $dataCount = count($data); - if ($totalPages === 0 || $currentPage >= $totalPages) { - break; + if (array_key_exists('count', $pagination)) { + $advertisedCount = $this->nonNegativeInteger( + $pagination['count'], + 'pagination.count' + ); + if ($advertisedCount !== $dataCount) { + throw new \RuntimeException( + 'Pterodactyl pagination count does not match the page payload.' + ); + } } - if ($currentPage < $page) { - throw new \RuntimeException('Pterodactyl pagination did not advance.'); + + $calculatedPages = max( + 1, + intdiv($total, $perPage) + ($total % $perPage === 0 ? 0 : 1) + ); + if ($totalPages !== $calculatedPages) { + throw new \RuntimeException( + 'Pterodactyl pagination total is inconsistent with its page bounds.' + ); + } + if ( + $currentPage !== $page + || $currentPage > $totalPages + ) { + throw new \RuntimeException( + 'Pterodactyl pagination skipped, repeated, or returned an unexpected page.' + ); + } + if ($totalPages > self::MAX_PAGINATION_PAGES) { + throw new \RuntimeException( + 'Pterodactyl pagination exceeds the safe page limit.' + ); + } + + $pageSnapshot = [ + 'total' => $total, + 'per_page' => $perPage, + 'total_pages' => $totalPages, + ]; + if ($paginationSnapshot === null) { + $paginationSnapshot = $pageSnapshot; + } elseif ($paginationSnapshot !== $pageSnapshot) { + throw new \RuntimeException( + 'Pterodactyl pagination metadata changed during the inventory read.' + ); } - $page = $currentPage + 1; + $expectedCount = $currentPage < $totalPages + ? $perPage + : $total - (($totalPages - 1) * $perPage); + if ($dataCount !== $expectedCount) { + throw new \RuntimeException( + 'Pterodactyl pagination page size is inconsistent with its total.' + ); + } + + foreach ($data as $resource) { + $identity = $this->paginatedResourceIdentity($resource); + if (isset($resourceIdentities[$identity])) { + throw new \RuntimeException( + 'Pterodactyl pagination returned a duplicate resource.' + ); + } + + $resourceIdentities[$identity] = true; + $resources[] = $resource; + } + + if (count($resources) > $total) { + throw new \RuntimeException( + 'Pterodactyl pagination returned more resources than advertised.' + ); + } + + if ($currentPage === $totalPages) { + if (count($resources) !== $total) { + throw new \RuntimeException( + 'Pterodactyl pagination ended before the advertised total.' + ); + } + + break; + } + + $page++; } return $resources; } + /** + * Pterodactyl's Fractal serializer calls the final page `total_pages`. + * Accept `last_page` as a compatible paginator alias, but never accept + * conflicting values when an intermediary supplies both. + * + * @param array $pagination + */ + private function paginationLastPage(array $pagination): int + { + $totalPages = array_key_exists('total_pages', $pagination) + ? $this->positiveInteger( + $pagination['total_pages'], + 'pagination.total_pages' + ) + : null; + $lastPage = array_key_exists('last_page', $pagination) + ? $this->positiveInteger( + $pagination['last_page'], + 'pagination.last_page' + ) + : null; + + if ($totalPages === null && $lastPage === null) { + throw new \RuntimeException( + 'Pterodactyl pagination is missing the final page.' + ); + } + if ( + $totalPages !== null + && $lastPage !== null + && $totalPages !== $lastPage + ) { + throw new \RuntimeException( + 'Pterodactyl pagination contains conflicting final pages.' + ); + } + + return $totalPages ?? $lastPage; + } + + private function paginatedResourceIdentity(mixed $resource): string + { + if (! is_array($resource)) { + throw new \RuntimeException( + 'Pterodactyl returned an invalid paginated resource.' + ); + } + + $object = $resource['object'] ?? null; + $attributes = $resource['attributes'] ?? null; + if ( + ! is_string($object) + || trim($object) === '' + || ! is_array($attributes) + ) { + throw new \RuntimeException( + 'Pterodactyl returned an invalid paginated resource identity.' + ); + } + + return trim($object).':'.$this->positiveInteger( + $attributes['id'] ?? null, + 'paginated_resource.id' + ); + } + private function get(string $path, array $query): array { try { @@ -776,6 +929,44 @@ private function attributes(array $resource, string $expectedObject): array return $attributes; } + /** + * Pterodactyl's Fractal serializer merges included resources into the + * transformed data before wrapping it in `attributes`. Accept the legacy + * root-level shape only when the official nested relationship container is + * absent; never let a conflicting root value override stock API data. + * + * @return list> + */ + private function relationshipData( + array $resource, + array $attributes, + string $object, + string $relationship, + string $remediation = '' + ): array { + $relationships = array_key_exists('relationships', $attributes) + ? $attributes['relationships'] + : ($resource['relationships'] ?? null); + $relationshipResource = is_array($relationships) + ? ($relationships[$relationship] ?? null) + : null; + $data = is_array($relationshipResource) + ? ($relationshipResource['data'] ?? null) + : null; + + if (! is_array($data) || ! array_is_list($data)) { + $message = "Pterodactyl {$object} inventory is missing the " + ."{$relationship} relationship."; + if ($remediation !== '') { + $message .= ' '.$remediation; + } + + throw new \RuntimeException($message); + } + + return $data; + } + private function positiveInteger(mixed $value, string $field): int { $value = $this->integerValue($value, $field); diff --git a/Services/QuoteRateLimitConfigurationService.php b/Services/QuoteRateLimitConfigurationService.php new file mode 100644 index 0000000..18b4232 --- /dev/null +++ b/Services/QuoteRateLimitConfigurationService.php @@ -0,0 +1,104 @@ +|null $config + */ + public function __construct(private readonly ?array $config = null) + { + } + + /** + * @return array{per_ip: int, global: int, panel_identity: string} + */ + public function configuration(): array + { + $config = $this->config ?? $this->extensionConfig(); + $panelUrl = trim((string) ($config['pterodactyl_url'] ?? '')); + + try { + $panelIdentity = PanelEndpointIdentity::hash($panelUrl); + } catch (\InvalidArgumentException $exception) { + throw new InvalidStockConfigurationException( + 'Dynamic quote rate limiting requires a valid Pterodactyl panel URL.', + previous: $exception + ); + } + + return [ + 'per_ip' => $this->boundedInteger( + $config['quote_rate_limit_per_ip'] ?? null, + self::DEFAULT_PER_IP, + self::MAX_PER_IP, + 'per-IP quote rate limit' + ), + 'global' => $this->boundedInteger( + $config['quote_rate_limit_global'] ?? null, + self::DEFAULT_GLOBAL, + self::MAX_GLOBAL, + 'global quote rate limit' + ), + 'panel_identity' => $panelIdentity, + ]; + } + + private function boundedInteger( + mixed $value, + int $default, + int $maximum, + string $label + ): int { + if ($value === null || $value === '') { + return $default; + } + if ( + ! is_int($value) + && ! ( + is_string($value) + && preg_match('/^(0|[1-9]\d*)$/D', $value) === 1 + ) + ) { + throw new InvalidStockConfigurationException( + "The {$label} must be a whole number." + ); + } + + $validated = filter_var($value, FILTER_VALIDATE_INT); + if ($validated === false || $validated < 1 || $validated > $maximum) { + throw new InvalidStockConfigurationException( + "The {$label} must be between 1 and {$maximum} requests per minute." + ); + } + + return $validated; + } + + /** + * @return array + */ + private function extensionConfig(): array + { + return Extension::query() + ->where('extension', 'DynamicPterodactyl') + ->where('enabled', true) + ->first() + ?->settings + ->pluck('value', 'key') + ->toArray() ?? []; + } +} diff --git a/Services/QuoteRateLimiterService.php b/Services/QuoteRateLimiterService.php new file mode 100644 index 0000000..db8fdf6 --- /dev/null +++ b/Services/QuoteRateLimiterService.php @@ -0,0 +1,38 @@ +configuration->configuration(); + $panelIdentity = $configuration['panel_identity']; + + return [ + Limit::perMinute($configuration['per_ip'])->by( + 'dynamic-pterodactyl:quotes:ip:' + .$panelIdentity.':'.$request->ip() + ), + Limit::perMinute($configuration['global'])->by( + 'dynamic-pterodactyl:quotes:panel:'.$panelIdentity + ), + ]; + }); + } +} diff --git a/Services/ReservationConfigurationService.php b/Services/ReservationConfigurationService.php index 3229f41..8b152d5 100644 --- a/Services/ReservationConfigurationService.php +++ b/Services/ReservationConfigurationService.php @@ -68,6 +68,10 @@ public function forCartItem(CartItem $cartItem): array } catch (InvalidResourceSelectionException|InvalidStockConfigurationException $exception) { throw new DisplayException($exception->getMessage(), previous: $exception); } + $this->assertExplicitResourceSelections( + (array) ($cartItem->config_options ?? []), + (array) ($stockConfiguration['sliders'] ?? []) + ); $selectedOptions = collect($cartItem->config_options ?? []) ->keyBy(fn ($option) => (int) data_get($option, 'option_id')); @@ -153,6 +157,54 @@ public function forCartItem(CartItem $cartItem): array ]; } + /** + * Quotes may use configured defaults for their first render, but a stored + * cart item is a billing input and must explicitly carry every active + * resource slider. Otherwise a slider attached after the checkout page was + * opened could default into the reservation while CartItem pricing omits + * its marginal charge. + * + * @param array $submittedOptions + * @param array> $sliders + */ + private function assertExplicitResourceSelections( + array $submittedOptions, + array $sliders + ): void { + $submittedIds = []; + if (array_is_list($submittedOptions)) { + foreach ($submittedOptions as $selection) { + $optionId = StrictInteger::parse( + data_get($selection, 'option_id') + ); + if ($optionId !== null) { + $submittedIds[$optionId] = true; + } + } + } else { + foreach (array_keys($submittedOptions) as $optionId) { + $optionId = StrictInteger::parse($optionId); + if ($optionId !== null) { + $submittedIds[$optionId] = true; + } + } + } + + foreach ($sliders as $slider) { + $optionId = StrictInteger::parse( + $slider['config_option_id'] ?? null + ); + if ($optionId !== null && isset($submittedIds[$optionId])) { + continue; + } + + throw new DisplayException( + 'The product resource options changed before reservation. ' + .'Reload checkout and explicitly select every resource again.' + ); + } + } + public function requiresReservation(int $productId): bool { $usesPterodactyl = Product::query() @@ -281,6 +333,185 @@ public function fingerprint(array $payload): string return hash('sha256', $this->canonicalJson($payload)); } + /** + * Prove that the allocation claim rows are the exact materialization of a + * signed checkout snapshot. + * + * Pending and paid commitments must still own active claims. Confirmed + * commitments must retain the same historical rows after their claims are + * released, so stock accounting can bridge stale Pterodactyl inventory + * without trusting a detached or rewritten allocation row. + * + * @param iterable $claims + * @return array + */ + public function verifiedAllocationSnapshot( + object $reservation, + iterable $claims + ): array { + $payload = $reservation->configuration_payload; + if (is_string($payload)) { + try { + $payload = json_decode( + $payload, + true, + 512, + JSON_THROW_ON_ERROR + ); + } catch (\JsonException $exception) { + throw new InvalidStockConfigurationException( + 'The checkout allocation snapshot is unreadable.', + previous: $exception + ); + } + } + + if ( + ($reservation->purpose ?? null) !== 'checkout' + || ! is_array($payload) + || ! is_string($reservation->configuration_fingerprint) + || ! hash_equals( + $reservation->configuration_fingerprint, + $this->fingerprint($payload) + ) + || (string) ($payload['panel_identity'] ?? '') + !== (string) $reservation->panel_identity + || StrictInteger::parse($payload['node_id'] ?? null) === null + || (int) $payload['node_id'] !== (int) $reservation->node_id + || StrictInteger::parse( + $payload['location_id'] ?? null + ) === null + || (int) $payload['location_id'] + !== (int) $reservation->location_id + || StrictInteger::parse( + data_get($payload, 'resources.memory') + ) === null + || (int) data_get($payload, 'resources.memory') + !== (int) $reservation->memory + || StrictInteger::parse( + data_get($payload, 'resources.cpu') + ) === null + || (int) data_get($payload, 'resources.cpu') + !== (int) $reservation->cpu + || StrictInteger::parse( + data_get($payload, 'resources.disk') + ) === null + || (int) data_get($payload, 'resources.disk') + !== (int) $reservation->disk + ) { + throw new InvalidStockConfigurationException( + 'The checkout allocation snapshot failed its immutable capacity integrity check.' + ); + } + + $rawExpected = $payload['allocations'] ?? null; + $requiredCount = StrictInteger::parse( + data_get($payload, 'allocation_requirements.required_count') + ); + if ( + ! is_array($rawExpected) + || $rawExpected === [] + || $requiredCount === null + || $requiredCount <= 0 + || count($rawExpected) !== $requiredCount + ) { + throw new InvalidStockConfigurationException( + 'The checkout allocation snapshot has no valid signed allocation set.' + ); + } + + $expected = []; + foreach ($rawExpected as $allocation) { + if (! is_array($allocation)) { + throw new InvalidStockConfigurationException( + 'The checkout allocation snapshot has an invalid signed allocation.' + ); + } + + $allocationId = StrictInteger::parse( + $allocation['allocation_id'] ?? null + ); + $port = StrictInteger::parse($allocation['port'] ?? null); + $ip = $allocation['ip'] ?? null; + $environmentKey = $allocation['environment_key'] ?? null; + $isPrimary = $allocation['is_primary'] ?? null; + if ( + $allocationId === null + || $allocationId <= 0 + || $port === null + || $port <= 0 + || $port > 65535 + || ! is_string($ip) + || trim($ip) === '' + || ( + $environmentKey !== null + && ! is_string($environmentKey) + ) + || ! is_bool($isPrimary) + ) { + throw new InvalidStockConfigurationException( + 'The checkout allocation snapshot has an invalid signed allocation.' + ); + } + + $expected[] = [ + 'panel_identity' => (string) $reservation->panel_identity, + 'node_id' => (int) $reservation->node_id, + 'allocation_id' => $allocationId, + 'ip' => $ip, + 'port' => $port, + 'environment_key' => $environmentKey, + 'is_primary' => $isPrimary, + ]; + } + usort( + $expected, + fn (array $left, array $right): int => + $left['allocation_id'] <=> $right['allocation_id'] + ); + + $claimRows = collect($claims)->values(); + $actual = $claimRows + ->map(fn (object $allocation): array => [ + 'panel_identity' => (string) $allocation->panel_identity, + 'node_id' => (int) $allocation->node_id, + 'allocation_id' => (int) $allocation->allocation_id, + 'ip' => (string) ($allocation->ip ?? ''), + 'port' => (int) $allocation->port, + 'environment_key' => $allocation->environment_key, + 'is_primary' => (bool) $allocation->is_primary, + ]) + ->sortBy('allocation_id') + ->values() + ->all(); + $allocationIds = array_column($actual, 'allocation_id'); + $status = (string) ($reservation->status ?? ''); + $releaseStateIsValid = match ($status) { + 'pending', 'paid_committed' => ! $claimRows->contains( + fn (object $allocation): bool => + $allocation->released_at !== null + ), + 'confirmed' => ! $claimRows->contains( + fn (object $allocation): bool => + $allocation->released_at === null + ), + default => false, + }; + + if ( + $expected !== $actual + || count(array_unique($allocationIds)) !== count($allocationIds) + || collect($actual)->where('is_primary', true)->count() !== 1 + || ! $releaseStateIsValid + ) { + throw new InvalidStockConfigurationException( + 'Allocation claims no longer match the immutable checkout reservation.' + ); + } + + return $payload; + } + private function canonicalMoney(mixed $unitPrice, int $quantity): string { if ( @@ -356,19 +587,41 @@ public function assertServiceMatches(Service $service, object $reservation): voi 'node_id' => (int) $reservation->node_id, ]; $payloadIdentity = [ - 'customer_id' => (int) ($payload['customer_id'] ?? 0), - 'server_extension_id' => (int) ($payload['server_extension_id'] ?? 0), + 'customer_id' => StrictInteger::parse( + $payload['customer_id'] ?? null + ), + 'server_extension_id' => StrictInteger::parse( + $payload['server_extension_id'] ?? null + ), 'panel_identity' => (string) ($payload['panel_identity'] ?? ''), - 'product_id' => (int) ($payload['product_id'] ?? 0), - 'plan_id' => (int) ($payload['plan_id'] ?? 0), - 'quantity' => (int) ($payload['quantity'] ?? 0), + 'product_id' => StrictInteger::parse( + $payload['product_id'] ?? null + ), + 'plan_id' => StrictInteger::parse( + $payload['plan_id'] ?? null + ), + 'quantity' => StrictInteger::parse( + $payload['quantity'] ?? null + ), 'currency_code' => strtoupper((string) ($payload['currency_code'] ?? '')), - 'user_id' => (int) ($payload['customer_id'] ?? 0), - 'memory' => (int) data_get($payload, 'resources.memory', 0), - 'cpu' => (int) data_get($payload, 'resources.cpu', 0), - 'disk' => (int) data_get($payload, 'resources.disk', 0), - 'location' => (int) ($payload['location_id'] ?? 0), - 'node_id' => (int) ($payload['node_id'] ?? 0), + 'user_id' => StrictInteger::parse( + $payload['customer_id'] ?? null + ), + 'memory' => StrictInteger::parse( + data_get($payload, 'resources.memory') + ), + 'cpu' => StrictInteger::parse( + data_get($payload, 'resources.cpu') + ), + 'disk' => StrictInteger::parse( + data_get($payload, 'resources.disk') + ), + 'location' => StrictInteger::parse( + $payload['location_id'] ?? null + ), + 'node_id' => StrictInteger::parse( + $payload['node_id'] ?? null + ), ]; $serviceIdentity = [ 'service_id' => (int) $service->id, @@ -390,6 +643,8 @@ public function assertServiceMatches(Service $service, object $reservation): voi if ( $reservationIdentity !== $payloadIdentity || $serviceIdentity !== $expectedServiceIdentity + || (int) $reservation->quantity !== 1 + || (int) $service->quantity !== 1 ) { throw new \RuntimeException( 'The service identity does not match its immutable capacity reservation.' diff --git a/Services/ReservationService.php b/Services/ReservationService.php index 6a7e8c4..80dfefe 100644 --- a/Services/ReservationService.php +++ b/Services/ReservationService.php @@ -21,6 +21,7 @@ use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Gate; use Illuminate\Support\Str; +use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\ReservationAllocation; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\ResourceReservation; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\Concerns\AuditsExtensionActions; @@ -178,6 +179,7 @@ public function reserveForCartItem(CartItem $cartItem): array } if ($existing !== null && $this->matchesSnapshot($existing, $snapshot)) { + $this->assertAllocationClaimsMatch($existing); $expiresAt = now()->addMinutes($this->ttlMinutes); DB::table('ptero_resource_reservations') @@ -586,8 +588,7 @@ public function preflightPaidService( $reservation ); $this->assertAllocationClaimsMatch( - $reservation, - true + $reservation ); }, 5); @@ -677,7 +678,7 @@ public function commitPaidService(Service $service, Invoice $invoice): bool } $this->configurationService->assertServiceMatches($lockedService, $reservation); - $this->assertAllocationClaimsMatch($reservation, true); + $this->assertAllocationClaimsMatch($reservation); DB::table('ptero_resource_reservations') ->where('id', $reservation->id) @@ -743,7 +744,7 @@ public function commitFreeService(Service $service): bool $this->configurationService->assertServiceMatches($lockedService, $reservation); if ($reservation->status === ResourceReservation::STATUS_PENDING) { - $this->assertAllocationClaimsMatch($reservation, true); + $this->assertAllocationClaimsMatch($reservation); } if ($reservation->status === ResourceReservation::STATUS_PENDING) { @@ -802,10 +803,7 @@ public function beginProvisioning(Service $service): ?array return null; } - $this->assertAllocationClaimsMatch( - $reservation, - $reservation->status === ResourceReservation::STATUS_PAID_COMMITTED - ); + $this->assertAllocationClaimsMatch($reservation); if ($reservation->status === 'confirmed') { return $this->provisioningContext($reservation, true); @@ -1038,6 +1036,160 @@ public function requestServiceCancellation(Service $service): bool }, 5); } + /** + * Return the integrity-checked checkout contract used to reconcile a + * cancellation after an external create may have succeeded without + * returning a response to Paymenter. + * + * This path is intentionally limited to an unconsumed paid commitment + * with no pinned external identity. It never creates or adopts a + * Pterodactyl customer. + * + * @return array|null + */ + public function cancellationReconciliationContext( + int|Service $service + ): ?array { + $serviceId = $service instanceof Service + ? (int) $service->id + : $service; + + return DB::transaction(function () use ($serviceId) { + $lockedService = Service::query() + ->whereKey($serviceId) + ->lockForUpdate() + ->firstOrFail(); + $reservation = $this->checkoutCommitmentQuery($serviceId) + ->lockForUpdate() + ->first(); + + if ($reservation === null) { + return null; + } + + return $this->buildCancellationReconciliationContext( + $lockedService, + $reservation, + true + ); + }, 5); + } + + /** + * Persist the exact external identity only after the provisioner has + * matched the candidate server to cancellationReconciliationContext(). + * Re-validate the complete signed checkout contract under the same row + * lock so a stale or competing cancellation worker cannot pin a different + * server. + * + * @param array $externalServer + * @return array + */ + public function pinCancellationServerIdentity( + int|Service $service, + array $externalServer, + int $expectedExternalUserId + ): array { + $serviceId = $service instanceof Service + ? (int) $service->id + : $service; + + return DB::transaction(function () use ( + $serviceId, + $externalServer, + $expectedExternalUserId + ) { + $lockedService = Service::query() + ->whereKey($serviceId) + ->lockForUpdate() + ->firstOrFail(); + $reservation = $this->checkoutCommitmentQuery($serviceId) + ->lockForUpdate() + ->first(); + if ($reservation === null) { + throw new PermanentProvisioningException( + 'The cancellation has no checkout commitment to reconcile.' + ); + } + + $context = $this->buildCancellationReconciliationContext( + $lockedService, + $reservation, + false + ); + if ($context['provisioning_in_flight']) { + throw new \RuntimeException( + 'Provisioning is still in flight; cancellation will retry.' + ); + } + + $this->assertCancellationServerMatchesContext( + $externalServer, + $context, + $serviceId, + $expectedExternalUserId + ); + $attributes = $externalServer['attributes'] ?? $externalServer; + $externalIdentity = $this->externalServerIdentity($attributes); + $storedIdentity = [ + 'external_server_id' => $reservation->external_server_id, + 'external_user_id' => $reservation->external_user_id, + 'external_server_uuid' => + $reservation->external_server_uuid, + 'external_server_identifier' => + $reservation->external_server_identifier, + ]; + $hasStoredIdentity = collect($storedIdentity) + ->contains(fn ($value): bool => $value !== null); + + if ($hasStoredIdentity) { + $storedIdentityMatches = + is_numeric($storedIdentity['external_server_id']) + && (int) $storedIdentity['external_server_id'] + === $externalIdentity['external_server_id'] + && is_numeric($storedIdentity['external_user_id']) + && (int) $storedIdentity['external_user_id'] + === $externalIdentity['external_user_id'] + && is_string( + $storedIdentity['external_server_uuid'] + ) + && hash_equals( + $storedIdentity['external_server_uuid'], + $externalIdentity['external_server_uuid'] + ) + && is_string( + $storedIdentity['external_server_identifier'] + ) + && hash_equals( + $storedIdentity['external_server_identifier'], + $externalIdentity[ + 'external_server_identifier' + ] + ); + if (! $storedIdentityMatches) { + throw new PermanentProvisioningException( + 'The cancellation found a conflicting pinned Pterodactyl server identity.' + ); + } + } else { + DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->update([ + ...$externalIdentity, + 'last_reconciled_at' => now(), + 'provisioning_started_at' => null, + 'provisioning_lease_id' => null, + 'updated_at' => now(), + ]); + } + + return [ + ...$context, + ...$externalIdentity, + ]; + }, 5); + } + /** * Finish cancellation only after the provisioner has established that the * external server is absent. @@ -1346,37 +1498,67 @@ public function cancel( string $source = 'system', ?User $actor = null ): bool { - $reservation = $this->getByToken($token); - if ($reservation === null) { + $reservationModel = ResourceReservation::query() + ->where('token', $token) + ->first(); + if ($reservationModel === null) { return false; } if ($actor !== null) { - $reservationModel = ResourceReservation::query()->where('token', $token)->first(); - if ($reservationModel !== null) { - Gate::forUser($actor)->authorize('cancel', $reservationModel); - } + Gate::forUser($actor)->authorize('cancel', $reservationModel); } - $updated = DB::table('ptero_resource_reservations') - ->where('token', $token) - ->where('status', 'pending') - ->whereNull('service_id') - ->update([ + $reservation = DB::transaction(function () use ( + $token, + $reason + ): ?object { + $reservation = DB::table('ptero_resource_reservations') + ->where('token', $token) + ->lockForUpdate() + ->first(); + if ( + $reservation === null + || $reservation->status !== 'pending' + || $reservation->service_id !== null + ) { + return null; + } + + $updated = DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->where('status', 'pending') + ->whereNull('service_id') + ->update([ 'status' => 'cancelled', 'admin_notes' => $reason, 'updated_at' => now(), - ]) > 0; + ]); + if ($updated !== 1) { + throw new \RuntimeException( + 'The reservation changed while cancellation was being committed.' + ); + } - if ($updated) { $this->releaseAllocationClaims((int) $reservation->id); - $this->safeAudit('reservation_cancelled', 'resource_reservation', $reservation->id, [ + + return $reservation; + }, 5); + if ($reservation === null) { + return false; + } + + $this->safeAudit( + 'reservation_cancelled', + 'resource_reservation', + $reservation->id, + [ 'source' => $source, 'node_id' => $reservation->node_id, - ]); - } + ] + ); - return $updated; + return true; } /** @@ -1945,10 +2127,10 @@ private function provisioningContext( public function applyCapacityHoldingScope(Builder $query): Builder { return $query->where(function (Builder $query) { - $query->where(function (Builder $query) { - $query->where('status', ResourceReservation::STATUS_PENDING) - ->where('expires_at', '>', now()); - })->orWhere('status', ResourceReservation::STATUS_PAID_COMMITTED); + $query->where( + 'status', + ResourceReservation::STATUS_PENDING + )->orWhere('status', ResourceReservation::STATUS_PAID_COMMITTED); }); } @@ -2068,6 +2250,248 @@ private function externalServerIdentity(array $attributes): array ]; } + /** + * @param object $reservation + * @return array + */ + private function buildCancellationReconciliationContext( + Service $service, + object $reservation, + bool $requireUnpinned + ): array { + if ( + $reservation->cancellation_requested_at === null + || $service->status !== Service::STATUS_CANCELLATION_PENDING + ) { + throw new PermanentProvisioningException( + 'The service has no durable cancellation request to reconcile.' + ); + } + if ( + $reservation->status + !== ResourceReservation::STATUS_PAID_COMMITTED + ) { + throw new PermanentProvisioningException( + 'Only an unconsumed paid commitment can use cancellation reconciliation.' + ); + } + + $storedIdentity = [ + $reservation->external_server_id, + $reservation->external_user_id, + $reservation->external_server_uuid, + $reservation->external_server_identifier, + ]; + if ( + $requireUnpinned + && collect($storedIdentity) + ->contains(fn ($value): bool => $value !== null) + ) { + throw new PermanentProvisioningException( + 'The cancellation already has a pinned Pterodactyl server identity.' + ); + } + + try { + $this->configurationService->assertServiceMatches( + $service, + $reservation + ); + $claims = DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservation->id) + ->lockForUpdate() + ->get(); + $payload = $this->configurationService + ->verifiedAllocationSnapshot($reservation, $claims); + } catch ( + InvalidStockConfigurationException|\RuntimeException $exception + ) { + throw new PermanentProvisioningException( + $exception->getMessage(), + previous: $exception + ); + } + + $identity = (array) ($payload['provisioning_identity'] ?? []); + $nestId = StrictInteger::parse($identity['nest_id'] ?? null); + $eggId = StrictInteger::parse($identity['egg_id'] ?? null); + $userExternalId = $identity['user_external_id'] ?? null; + if ( + $nestId === null + || $nestId <= 0 + || $eggId === null + || $eggId <= 0 + || ! is_string($userExternalId) + || $userExternalId === '' + ) { + throw new PermanentProvisioningException( + 'The cancellation checkout contract has no valid customer or image identity.' + ); + } + + $provisioningInFlight = + $reservation->provisioning_started_at !== null + && Carbon::parse($reservation->provisioning_started_at) + ->greaterThan( + now()->subMinutes(self::PROVISIONING_LEASE_MINUTES) + ); + + return [ + 'reservation_id' => (int) $reservation->id, + 'configuration_fingerprint' => + (string) $reservation->configuration_fingerprint, + 'status' => (string) $reservation->status, + 'panel_identity' => (string) $reservation->panel_identity, + 'external_server_external_id' => (string) $service->id, + 'node_id' => (int) $reservation->node_id, + 'location_id' => (int) $reservation->location_id, + 'memory' => (int) $reservation->memory, + 'cpu' => (int) $reservation->cpu, + 'disk' => (int) $reservation->disk, + 'allocations' => array_values( + (array) ($payload['allocations'] ?? []) + ), + 'client_allocation_limit' => 0, + 'nest_id' => $nestId, + 'egg_id' => $eggId, + 'user_external_id' => $userExternalId, + 'user_email' => $identity['user_email'] ?? null, + 'provisioning_in_flight' => $provisioningInFlight, + ]; + } + + /** + * @param array $server + * @param array $context + */ + private function assertCancellationServerMatchesContext( + array $server, + array $context, + int $serviceId, + int $expectedExternalUserId + ): void { + $attributes = $server['attributes'] ?? $server; + if (! is_array($attributes)) { + throw new PermanentProvisioningException( + 'Pterodactyl returned an invalid cancellation server response.' + ); + } + $externalIdentity = $this->externalServerIdentity($attributes); + if ( + $expectedExternalUserId <= 0 + || $externalIdentity['external_user_id'] + !== $expectedExternalUserId + || ! is_string($attributes['external_id'] ?? null) + || ! hash_equals( + (string) $serviceId, + $attributes['external_id'] + ) + ) { + throw new PermanentProvisioningException( + 'The cancellation candidate does not belong to the reserved Paymenter customer and service.' + ); + } + + foreach ([ + 'node' => $context['node_id'], + 'nest' => $context['nest_id'], + 'egg' => $context['egg_id'], + ] as $field => $expected) { + if ( + StrictInteger::parse($attributes[$field] ?? null) === null + || (int) $attributes[$field] !== (int) $expected + ) { + throw new PermanentProvisioningException( + "The cancellation candidate does not match reserved {$field}." + ); + } + } + + $limits = (array) ($attributes['limits'] ?? []); + foreach (['memory', 'cpu', 'disk'] as $resource) { + if ( + StrictInteger::parse($limits[$resource] ?? null) === null + || (int) $limits[$resource] + !== (int) $context[$resource] + ) { + throw new PermanentProvisioningException( + "The cancellation candidate does not match reserved {$resource}." + ); + } + } + if ( + StrictInteger::parse( + data_get($attributes, 'feature_limits.allocations') + ) === null + || (int) data_get( + $attributes, + 'feature_limits.allocations' + ) !== 0 + ) { + throw new PermanentProvisioningException( + 'The cancellation candidate permits unreserved client allocation changes.' + ); + } + + $assigned = data_get( + $attributes, + 'relationships.allocations.data', + data_get($server, 'relationships.allocations.data') + ); + if (! is_array($assigned)) { + throw new PermanentProvisioningException( + 'The cancellation candidate has no verifiable allocation set.' + ); + } + $assignedIds = []; + foreach ($assigned as $allocation) { + $allocationId = is_array($allocation) + ? StrictInteger::parse( + data_get($allocation, 'attributes.id') + ?? ($allocation['id'] ?? null) + ) + : null; + if ($allocationId === null || $allocationId <= 0) { + throw new PermanentProvisioningException( + 'The cancellation candidate has an invalid assigned allocation.' + ); + } + $assignedIds[] = $allocationId; + } + sort($assignedIds); + if (count(array_unique($assignedIds)) !== count($assignedIds)) { + throw new PermanentProvisioningException( + 'The cancellation candidate has duplicate assigned allocations.' + ); + } + + $reserved = collect($context['allocations'] ?? []); + $reservedIds = $reserved + ->map(fn (array $allocation): int => + (int) ($allocation['allocation_id'] ?? 0)) + ->sort() + ->values() + ->all(); + $primaryIds = $reserved + ->filter(fn (array $allocation): bool => + (bool) ($allocation['is_primary'] ?? false)) + ->map(fn (array $allocation): int => + (int) ($allocation['allocation_id'] ?? 0)) + ->values(); + if ( + $reservedIds === [] + || count(array_unique($reservedIds)) !== count($reservedIds) + || $primaryIds->count() !== 1 + || StrictInteger::parse($attributes['allocation'] ?? null) + !== (int) $primaryIds->first() + || $assignedIds !== $reservedIds + ) { + throw new PermanentProvisioningException( + 'The cancellation candidate allocation set does not exactly match the reservation.' + ); + } + } + /** * @param array{panel_identity: string, location_id: int} $scope */ @@ -2178,73 +2602,22 @@ private function moneyCents(mixed $value): ?int * Prove that the allocation claim rows are an exact materialization of the * fingerprinted payload before any external request can use them. */ - private function assertAllocationClaimsMatch(object $reservation, bool $requireActive): void + private function assertAllocationClaimsMatch(object $reservation): void { - $payload = json_decode( - (string) $reservation->configuration_payload, - true, - 512, - JSON_THROW_ON_ERROR - ); - if ( - ! is_array($payload) - || ! hash_equals( - (string) $reservation->configuration_fingerprint, - $this->configurationService->fingerprint($payload) - ) - || (string) ($payload['panel_identity'] ?? '') !== (string) $reservation->panel_identity - || (int) ($payload['node_id'] ?? 0) !== (int) $reservation->node_id - || (int) data_get($payload, 'resources.memory', 0) !== (int) $reservation->memory - || (int) data_get($payload, 'resources.cpu', 0) !== (int) $reservation->cpu - || (int) data_get($payload, 'resources.disk', 0) !== (int) $reservation->disk - ) { - throw new PermanentProvisioningException( - 'The capacity reservation payload no longer matches its immutable fingerprint.' - ); - } - - $expected = collect($payload['allocations'] ?? []) - ->map(fn (array $allocation) => [ - 'panel_identity' => (string) $reservation->panel_identity, - 'node_id' => (int) $reservation->node_id, - 'allocation_id' => (int) ($allocation['allocation_id'] ?? 0), - 'ip' => (string) ($allocation['ip'] ?? ''), - 'port' => (int) ($allocation['port'] ?? 0), - 'environment_key' => $allocation['environment_key'] ?? null, - 'is_primary' => (bool) ($allocation['is_primary'] ?? false), - ]) - ->sortBy('allocation_id') - ->values() - ->all(); $claims = DB::table('ptero_reservation_allocations') ->where('reservation_id', $reservation->id) ->lockForUpdate() ->get(); - $actual = $claims - ->map(fn ($allocation) => [ - 'panel_identity' => (string) $allocation->panel_identity, - 'node_id' => (int) $allocation->node_id, - 'allocation_id' => (int) $allocation->allocation_id, - 'ip' => (string) ($allocation->ip ?? ''), - 'port' => (int) $allocation->port, - 'environment_key' => $allocation->environment_key, - 'is_primary' => (bool) $allocation->is_primary, - ]) - ->sortBy('allocation_id') - ->values() - ->all(); - if ( - $expected === [] - || $expected !== $actual - || collect($actual)->where('is_primary', true)->count() !== 1 - || ( - $requireActive - && $claims->contains(fn ($allocation) => $allocation->released_at !== null) - ) - ) { + try { + $this->configurationService->verifiedAllocationSnapshot( + $reservation, + $claims + ); + } catch (InvalidStockConfigurationException $exception) { throw new PermanentProvisioningException( - 'Allocation claims no longer match the immutable capacity reservation.' + $exception->getMessage(), + previous: $exception ); } } @@ -2257,7 +2630,7 @@ private function persistFulfillmentService(Service $service): void ); } - private function releaseAllocationClaims(int $reservationId): void + protected function releaseAllocationClaims(int $reservationId): void { DB::table('ptero_reservation_allocations') ->where('reservation_id', $reservationId) diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index 1b14901..87e060a 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -3,6 +3,7 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Services; use Illuminate\Support\Facades\DB; +use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\NodeCapacityPolicy; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\ResourceReservation; @@ -10,9 +11,20 @@ class ResourceCalculationService { private ?PterodactylInventoryService $inventory; - public function __construct(?PterodactylInventoryService $inventory = null) - { + private ReservationConfigurationService $configuration; + + private UpgradeReservationIntegrityService $upgradeIntegrity; + + public function __construct( + ?PterodactylInventoryService $inventory = null, + ?ReservationConfigurationService $configuration = null, + ?UpgradeReservationIntegrityService $upgradeIntegrity = null + ) { $this->inventory = $inventory; + $this->configuration = $configuration + ?? new ReservationConfigurationService; + $this->upgradeIntegrity = $upgradeIntegrity + ?? new UpgradeReservationIntegrityService; } /** @@ -432,16 +444,13 @@ private function buildNodeAvailability( if (collect($servers)->contains( fn (array $server): bool => (int) ( $server['allocation_limit'] ?? 0 - ) > 1 + ) > 0 )) { - // In Pterodactyl 1.11, a customer can delete any non-primary - // allocation whenever allocation_limit is nonzero, then add a - // replacement once the assigned count falls below that limit. - // A limit above one can therefore consume a port that Paymenter - // promised to an unpaid seven-day commitment even when the server - // initially has no allocation headroom. Dynamic servers use zero; - // a legacy primary-only server with a total limit of one is safe. - $reasons[] = 'customer_allocation_headroom'; + // Exact port guarantees require Paymenter to be the only allocation + // authority. Any nonzero client allocation limit enables the + // customer-managed allocation workflow, even if the currently + // assigned set has no immediate headroom. + $reasons[] = 'customer_allocation_management'; } if ($availableAllocations === []) { $reasons[] = 'no_available_allocation'; @@ -591,12 +600,12 @@ private function holdingReservations( ) ->whereIn('reservations.node_id', $nodeIds) ->where(function ($query): void { - $query->where(function ($query): void { - $query->where( - 'reservations.status', - ResourceReservation::STATUS_PENDING - )->where('reservations.expires_at', '>', now()); - })->orWhere( + // A pending row keeps holding stock until cleanup atomically + // changes its status and releases its allocation claims. + $query->where( + 'reservations.status', + ResourceReservation::STATUS_PENDING + )->orWhere( 'reservations.status', ResourceReservation::STATUS_PAID_COMMITTED )->orWhere(function ($query): void { @@ -628,7 +637,6 @@ private function holdingReservations( 'reservations.external_server_id', 'reservations.external_server_uuid', 'reservations.external_server_identifier', - 'reservations.configuration_payload', 'reservations.memory', 'reservations.cpu', 'reservations.disk', @@ -693,8 +701,10 @@ private function holdingReservations( /** * A completed upgrade supersedes the checkout vector and every older - * upgrade for the same service. Completion time is authoritative; the - * immutable row ID breaks a same-timestamp tie. + * upgrade for the same service. Upgrades are created serially under the + * one-active-upgrade guard, so the immutable ServiceUpgrade identity is + * authoritative. Reservation timestamps are operational metadata and + * must not be able to move an older target ahead of a newer one. * * @param list $expectations */ @@ -706,23 +716,16 @@ private function latestConfirmedTarget(array $expectations): object )); $candidates = $upgrades === [] ? $expectations : $upgrades; - usort($candidates, function (object $left, object $right): int { - $leftTime = strtotime((string) ( - $left->consumed_at - ?? $left->updated_at - ?? $left->created_at - ?? '' - )) ?: 0; - $rightTime = strtotime((string) ( - $right->consumed_at - ?? $right->updated_at - ?? $right->created_at - ?? '' - )) ?: 0; - - return [$leftTime, (int) $left->id] - <=> [$rightTime, (int) $right->id]; - }); + usort( + $candidates, + fn (object $left, object $right): int => [ + (int) ($left->service_upgrade_id ?? 0), + (int) $left->id, + ] <=> [ + (int) ($right->service_upgrade_id ?? 0), + (int) $right->id, + ] + ); return $candidates[array_key_last($candidates)]; } @@ -800,18 +803,10 @@ private function confirmedExternalIdentity( $identifiers = []; foreach ($expectations as $expectation) { - $payload = is_array($expectation->configuration_payload ?? null) - ? $expectation->configuration_payload - : json_decode( - (string) ($expectation->configuration_payload ?? ''), - true - ); - $id = (int) ( - $expectation->external_server_id - ?? (is_array($payload) - ? ($payload['external_server_id'] ?? 0) - : 0) - ); + // External server identity is materialized only after the + // Pterodactyl response is reconciled. Never infer it from mutable + // or unsigned JSON when calculating confirmed stock overlays. + $id = (int) ($expectation->external_server_id ?? 0); if ($id > 0) { $ids[$id] = true; } @@ -902,47 +897,51 @@ private function reservedAllocationClaims( return []; } - $query = DB::table('ptero_reservation_allocations as allocations') - ->join( - 'ptero_resource_reservations as reservations', - 'reservations.id', - '=', - 'allocations.reservation_id' - ) + // Start from commitments and join every claim by reservation identity + // only. Claim-side panel, node, and release fields are evidence to + // validate, never query filters. Validate all active commitments before + // narrowing to this panel/node so drift cannot move itself out of view. + $rows = DB::table('ptero_resource_reservations as reservations') ->leftJoin( 'services', 'services.id', '=', 'reservations.service_id' ) - ->where( - 'reservations.panel_identity', - $this->inventory()->panelIdentity() + ->leftJoin( + 'ptero_reservation_allocations as allocations', + 'allocations.reservation_id', + '=', + 'reservations.id' + ) + ->leftJoin( + 'service_upgrades as upgrades', + 'upgrades.id', + '=', + 'reservations.service_upgrade_id' + ) + ->leftJoin( + 'products as upgrade_products', + 'upgrade_products.id', + '=', + 'upgrades.product_id' ) - ->whereColumn( - 'allocations.panel_identity', - 'reservations.panel_identity' + ->leftJoin( + 'invoices as upgrade_invoices', + 'upgrade_invoices.id', + '=', + 'upgrades.invoice_id' ) - ->whereIn('allocations.node_id', $nodeIds) ->where(function ($query): void { - $query->where(function ($query): void { - $query->whereNull('allocations.released_at') - ->where(function ($query): void { - $query->where(function ($query): void { - $query->where( - 'reservations.status', - ResourceReservation::STATUS_PENDING - )->where( - 'reservations.expires_at', - '>', - now() - ); - })->orWhere( - 'reservations.status', - ResourceReservation::STATUS_PAID_COMMITTED - ); - }); - })->orWhere(function ($query): void { + // TTL expiry alone is not a state transition. Keep the row + // conservative until cleanup releases stock in one transaction. + $query->where( + 'reservations.status', + ResourceReservation::STATUS_PENDING + )->orWhere( + 'reservations.status', + ResourceReservation::STATUS_PAID_COMMITTED + )->orWhere(function ($query): void { $query->where( 'reservations.status', ResourceReservation::STATUS_CONFIRMED @@ -954,78 +953,256 @@ private function reservedAllocationClaims( 'cancelled' ); }); + })->orWhere(function ($query): void { + // Terminal rows must not retain a database allocation + // claim. Include them solely to fail closed until cleanup. + $query->whereNotNull('allocations.id') + ->whereNull('allocations.released_at'); }); - }); - - if ($excludeReservationToken !== null) { - $query->where('reservations.token', '!=', $excludeReservationToken); - } - - return $query + }) ->get([ - 'allocations.node_id', - 'allocations.allocation_id', - 'allocations.ip', - 'allocations.released_at', + 'reservations.id as reservation_id', + 'reservations.token', + 'reservations.purpose', + 'reservations.panel_identity', + 'reservations.service_id', + 'reservations.service_upgrade_id', + 'reservations.upgrade_guard_id', + 'reservations.server_extension_id', + 'reservations.invoice_id', + 'reservations.user_id', + 'reservations.product_id', + 'reservations.plan_id', + 'reservations.quantity', + 'reservations.currency_code', + 'reservations.node_id', + 'reservations.location_id', + 'reservations.memory', + 'reservations.cpu', + 'reservations.disk', + 'reservations.reserved_memory', + 'reservations.reserved_cpu', + 'reservations.reserved_disk', + 'reservations.external_server_id', + 'reservations.external_user_id', + 'reservations.external_server_uuid', + 'reservations.external_server_identifier', + 'reservations.calculated_price', + 'reservations.pricing_version', + 'reservations.formula_version', + 'reservations.expires_at', + 'reservations.consumed_at', 'reservations.status', + 'reservations.configuration_fingerprint', 'reservations.configuration_payload', 'services.status as service_status', - ]) - ->groupBy('node_id') - ->map(function ($rows): array { - $holdingOrActive = $rows->filter( - fn ($row): bool => in_array( - $row->status, - [ - ResourceReservation::STATUS_PENDING, - ResourceReservation::STATUS_PAID_COMMITTED, - ResourceReservation::STATUS_CONFIRMED, - ], - true - ) + 'services.user_id as service_user_id', + 'services.product_id as service_product_id', + 'services.plan_id as service_plan_id', + 'services.quantity as service_quantity', + 'services.currency_code as service_currency_code', + 'allocations.id as claim_row_id', + 'allocations.panel_identity as claim_panel_identity', + 'allocations.node_id as claim_node_id', + 'allocations.allocation_id', + 'allocations.ip', + 'allocations.port', + 'allocations.environment_key', + 'allocations.is_primary', + 'allocations.released_at', + 'upgrades.id as upgrade_id', + 'upgrades.service_id as upgrade_service_id', + 'upgrades.product_id as upgrade_product_id', + 'upgrades.plan_id as upgrade_plan_id', + 'upgrades.invoice_id as upgrade_invoice_id', + 'upgrades.status as upgrade_status', + 'upgrades.active_service_guard_id as upgrade_active_service_guard_id', + 'upgrades.source_snapshot as upgrade_source_snapshot', + 'upgrades.target_snapshot as upgrade_target_snapshot', + 'upgrades.source_fingerprint as upgrade_source_fingerprint', + 'upgrades.target_fingerprint as upgrade_target_fingerprint', + 'upgrades.quoted_amount as upgrade_quoted_amount', + 'upgrades.currency_code as upgrade_currency_code', + 'upgrade_products.server_id as upgrade_product_server_id', + 'upgrade_invoices.status as upgrade_invoice_status', + 'upgrade_invoices.user_id as upgrade_invoice_user_id', + 'upgrade_invoices.currency_code as upgrade_invoice_currency_code', + ]); + + if ($rows->isEmpty()) { + return []; + } + + $result = []; + + foreach ($rows->groupBy('reservation_id') as $reservationRows) { + $reservation = $reservationRows->first(); + $claims = $reservationRows + ->filter( + fn (object $row): bool => + $row->claim_row_id !== null + ) + ->map(fn (object $row): object => (object) [ + 'reservation_id' => (int) $row->reservation_id, + 'panel_identity' => + (string) $row->claim_panel_identity, + 'node_id' => (int) $row->claim_node_id, + 'allocation_id' => (int) $row->allocation_id, + 'ip' => $row->ip, + 'port' => (int) $row->port, + 'environment_key' => $row->environment_key, + 'is_primary' => (bool) $row->is_primary, + 'released_at' => $row->released_at, + ]) + ->values(); + $isActive = $reservation->status + === ResourceReservation::STATUS_PENDING + || $reservation->status + === ResourceReservation::STATUS_PAID_COMMITTED + || ( + $reservation->status + === ResourceReservation::STATUS_CONFIRMED + && $reservation->service_status !== 'cancelled' ); - $dedicated = $rows->filter(function ($row): bool { - $payload = json_decode( - (string) $row->configuration_payload, - true + if (! $isActive) { + throw new InvalidStockConfigurationException( + 'A terminal capacity commitment still owns an unreleased allocation claim.' + ); + } + + $payload = null; + if ($reservation->purpose === 'checkout') { + $payload = $this->configuration + ->verifiedAllocationSnapshot($reservation, $claims); + } elseif ($reservation->purpose === 'upgrade') { + if ($claims->isNotEmpty()) { + throw new InvalidStockConfigurationException( + 'A resource upgrade unexpectedly owns checkout allocation claims.' ); + } + $this->upgradeIntegrity->verifiedSnapshot( + (object) [ + 'id' => $reservation->upgrade_id, + 'service_id' => + $reservation->upgrade_service_id, + 'product_id' => + $reservation->upgrade_product_id, + 'plan_id' => + $reservation->upgrade_plan_id, + 'invoice_id' => + $reservation->upgrade_invoice_id, + 'status' => $reservation->upgrade_status, + 'active_service_guard_id' => + $reservation + ->upgrade_active_service_guard_id, + 'source_snapshot' => + $reservation->upgrade_source_snapshot, + 'target_snapshot' => + $reservation->upgrade_target_snapshot, + 'source_fingerprint' => + $reservation->upgrade_source_fingerprint, + 'target_fingerprint' => + $reservation->upgrade_target_fingerprint, + 'quoted_amount' => + $reservation->upgrade_quoted_amount, + 'currency_code' => + $reservation->upgrade_currency_code, + 'service_user_id' => + $reservation->service_user_id, + 'service_product_id' => + $reservation->service_product_id, + 'service_plan_id' => + $reservation->service_plan_id, + 'service_quantity' => + $reservation->service_quantity, + 'service_currency_code' => + $reservation->service_currency_code, + 'product_server_id' => + $reservation->upgrade_product_server_id, + 'invoice_status' => + $reservation->upgrade_invoice_status, + 'invoice_user_id' => + $reservation->upgrade_invoice_user_id, + 'invoice_currency_code' => + $reservation->upgrade_invoice_currency_code, + ], + $reservation + ); + } else { + throw new InvalidStockConfigurationException( + 'An active capacity commitment has an unknown purpose.' + ); + } - return is_array($payload) - && data_get( - $payload, - 'allocation_requirements.dedicated_ip' - ) === true; - }); + if ( + ! hash_equals( + (string) $reservation->panel_identity, + $this->inventory()->panelIdentity() + ) + || ! in_array( + (int) $reservation->node_id, + $nodeIds, + true + ) + ) { + continue; + } - return [ - 'ids' => $holdingOrActive - ->pluck('allocation_id') - ->map(fn ($id): int => (int) $id) - ->unique() - ->values() - ->all(), - 'ips' => $holdingOrActive - ->pluck('ip') - ->filter(fn ($ip): bool => is_string($ip) && $ip !== '') - ->map(fn (string $ip): string => $this->canonicalIp($ip)) - ->unique() - ->values() - ->all(), - 'blocked_ips' => $dedicated - ->pluck('ip') - ->filter( - fn ($ip): bool => is_string($ip) && $ip !== '' - ) - ->map( - fn (string $ip): string => - $this->canonicalIp($ip) - ) - ->unique() - ->values() - ->all(), - ]; - }) - ->all(); + // Self-exclusion changes arithmetic only. The excluded commitment + // must still pass integrity checks before the UI may reuse its + // capacity during a cart edit. + if ( + $excludeReservationToken !== null + && hash_equals( + (string) $reservation->token, + $excludeReservationToken + ) + ) { + continue; + } + if ($reservation->purpose !== 'checkout') { + continue; + } + + $nodeId = (int) $reservation->node_id; + $result[$nodeId] ??= [ + 'ids' => [], + 'ips' => [], + 'blocked_ips' => [], + ]; + $dedicated = data_get( + $payload, + 'allocation_requirements.dedicated_ip' + ) === true; + foreach ($claims as $claim) { + $allocationId = (int) $claim->allocation_id; + $ip = (string) ($claim->ip ?? ''); + $result[$nodeId]['ids'][$allocationId] = $allocationId; + if ($ip === '') { + continue; + } + $canonicalIp = $this->canonicalIp($ip); + $result[$nodeId]['ips'][$canonicalIp] = $canonicalIp; + if ($dedicated) { + $result[$nodeId]['blocked_ips'][$canonicalIp] + = $canonicalIp; + } + } + } + + foreach ($result as &$claims) { + $claims['ids'] = array_values($claims['ids']); + $claims['ips'] = array_values($claims['ips']); + $claims['blocked_ips'] = array_values( + $claims['blocked_ips'] + ); + sort($claims['ids'], SORT_NUMERIC); + sort($claims['ips'], SORT_STRING); + sort($claims['blocked_ips'], SORT_STRING); + } + unset($claims); + + return $result; } private function canonicalIp(string $ip): string diff --git a/Services/UpgradeReservationService.php b/Services/UpgradeReservationService.php index b8ff9e9..a0e27ae 100644 --- a/Services/UpgradeReservationService.php +++ b/Services/UpgradeReservationService.php @@ -11,6 +11,7 @@ use App\Models\ServiceUpgrade; use App\Services\Invoice\CancelInvoiceService; use App\Services\Invoice\CapacityInvoicePaymentService; +use App\Services\ServiceUpgrade\CapacityUpgradeReservationIdentity; use App\Services\ServiceUpgrade\ServiceUpgradeService; use App\Support\PanelEndpointIdentity; use App\Support\StrictInteger; @@ -25,10 +26,15 @@ class UpgradeReservationService { + private readonly UpgradeReservationIntegrityService $integrity; + public function __construct( private readonly PterodactylInventoryService $inventory, - private readonly ResourceCalculationService $resources + private readonly ResourceCalculationService $resources, + ?UpgradeReservationIntegrityService $integrity = null ) { + $this->integrity = $integrity + ?? new UpgradeReservationIntegrityService; } /** @@ -83,6 +89,7 @@ public function reserveForUpgrade( 'The paid upgrade commitment does not match this configuration.' ); } + $this->integrity->verifiedSnapshot($upgrade, $existing); return $existing; } @@ -149,10 +156,8 @@ public function reserveForUpgrade( 'currency_code' => strtoupper((string) $upgrade->currency_code), 'configuration_fingerprint' => $fingerprint, 'configuration_payload' => $payload, - 'pricing_version' => hash('sha256', json_encode([ - 'quoted_amount' => (string) $upgrade->quoted_amount, - 'currency_code' => strtoupper((string) $upgrade->currency_code), - ], JSON_THROW_ON_ERROR)), + 'pricing_version' => + $this->integrity->pricingVersion($upgrade), 'formula_version' => 'dynamic-upgrade-v1', // Full target values are provisioning truth. 'memory' => $context['target']['memory'], @@ -183,13 +188,16 @@ public function reserveForUpgrade( if ($existing !== null) { $existing->fill($values); $existing->save(); - - return $existing->fresh(); + $saved = $existing->fresh(); + } else { + $saved = UpgradeReservation::create(array_merge($values, [ + 'token' => Str::random(64), + ]))->fresh(); } - return UpgradeReservation::create(array_merge($values, [ - 'token' => Str::random(64), - ])); + $this->integrity->verifiedSnapshot($upgrade, $saved); + + return $saved; }, 5); } @@ -234,17 +242,16 @@ public function commitPaidUpgrade( ->lockForUpdate() ->firstOrFail(); - if ($reservation->status === 'paid_committed') { - app(ServiceUpgradeService::class)->markPaidCommitted($lockedUpgrade); - - return; - } - if ($reservation->status !== 'pending') { + $alreadyPaid = $reservation->status === 'paid_committed'; + if (! $alreadyPaid && $reservation->status !== 'pending') { throw new DisplayException( 'The upgrade capacity commitment is no longer payable.' ); } - if ($reservation->guaranteed_until?->isPast()) { + if ( + ! $alreadyPaid + && $reservation->guaranteed_until?->isPast() + ) { throw new DisplayException( 'The upgrade capacity guarantee has expired.' ); @@ -267,6 +274,14 @@ public function commitPaidUpgrade( 'The paid invoice does not belong to this service upgrade.' ); } + if ( + $lockedInvoice !== null + && $lockedInvoice->status !== Invoice::STATUS_PAID + ) { + throw new \RuntimeException( + 'The upgrade invoice is not paid.' + ); + } if ( $lockedInvoice === null && ((float) $lockedUpgrade->quoted_amount > 0 @@ -287,12 +302,14 @@ public function commitPaidUpgrade( } } - $reservation->forceFill([ - 'status' => 'paid_committed', - 'invoice_id' => $lockedInvoice?->id, - 'paid_committed_at' => now(), - 'last_provisioning_error' => null, - ])->save(); + if (! $alreadyPaid) { + $reservation->forceFill([ + 'status' => 'paid_committed', + 'invoice_id' => $lockedInvoice?->id, + 'paid_committed_at' => now(), + 'last_provisioning_error' => null, + ])->save(); + } app(ServiceUpgradeService::class)->markPaidCommitted($lockedUpgrade); }, 5); @@ -301,9 +318,9 @@ public function commitPaidUpgrade( } /** - * Run before the invoice coordinator opens its paid transaction. Invalid - * commitments are persisted first, then surfaced to the caller so a - * gateway cannot turn an expired or drifted upgrade into a paid invoice. + * Run while the invoice coordinator holds its paid transaction open. + * Invalid commitments are persisted and surfaced without throwing so + * external payment evidence and the needs-attention state commit together. */ public function preflightPaidUpgrade( ServiceUpgrade $upgrade, @@ -682,6 +699,11 @@ public function completeProvisioning( ServiceUpgrade $upgrade, ?string $leaseId ): void { + if (DB::transactionLevel() === 0) { + throw new \RuntimeException( + 'Upgrade completion requires the core completion transaction.' + ); + } if ($leaseId === null || $leaseId === '') { throw new \RuntimeException('An upgrade provisioning lease is required.'); } @@ -693,9 +715,17 @@ public function completeProvisioning( ->firstOrFail(); if ($reservation->status === 'confirmed') { + if ($upgrade->status !== ServiceUpgrade::STATUS_COMPLETED) { + throw new \RuntimeException( + 'The confirmed capacity commitment has no completed core upgrade.' + ); + } + return; } if ( + $upgrade->status !== ServiceUpgrade::STATUS_PROVISIONING + || $reservation->status !== 'paid_committed' || ! hash_equals((string) $reservation->provisioning_lease_id, $leaseId) ) { @@ -703,6 +733,14 @@ public function completeProvisioning( 'The upgrade provisioning lease is stale or invalid.' ); } + if ( + ($integrityFailure = $this->reservationIntegrityError( + $upgrade, + $reservation + )) !== null + ) { + throw new \RuntimeException($integrityFailure); + } $reservation->forceFill([ 'status' => 'confirmed', @@ -1334,9 +1372,9 @@ private function wholeNumber(mixed $value, string $label): int { $numeric = StrictInteger::parse($value) ?? StrictInteger::parseStoredDecimal($value); - if ($numeric === null || $numeric < 0) { + if ($numeric === null || $numeric <= 0) { throw new InvalidStockConfigurationException( - "The {$label} value must be a non-negative whole number." + "The {$label} value must be a positive whole number." ); } @@ -1349,11 +1387,6 @@ private function metadataInteger(object $option, string $key): int $option->getMetadata($key), "{$option->name} {$key}" ); - if ($key === 'step' && $value <= 0) { - throw new InvalidStockConfigurationException( - "{$option->name} step must be positive." - ); - } return $value; } @@ -1362,106 +1395,37 @@ private function reservationFingerprint( ServiceUpgrade $upgrade, array $context ): string { - return hash('sha256', json_encode([ - 'upgrade_id' => (int) $upgrade->id, - 'source_fingerprint' => (string) $upgrade->source_fingerprint, - 'target_fingerprint' => (string) $upgrade->target_fingerprint, - 'panel_identity' => $context['panel_identity'], - 'node_id' => $context['node_id'], - 'location_id' => $context['location_id'], - 'external_server_id' => $context['external_server_id'], - 'external_server_uuid' => $context['external_server_uuid'], - 'external_server_identifier' => - $context['external_server_identifier'], - 'external_server_external_id' => - $context['external_server_external_id'], - 'external_user_id' => $context['external_user_id'], - 'user_external_id' => $context['user_external_id'], - 'user_email' => $context['user_email'], - 'nest_id' => $context['nest_id'], - 'egg_id' => $context['egg_id'], - 'preserved_build' => $context['preserved_build'], - 'allocation_id' => $context['allocation_id'], - 'assigned_allocation_ids' => $context['assigned_allocation_ids'], - 'source' => $context['source'], - 'target' => $context['target'], - 'delta' => $context['delta'], - 'quoted_amount' => (string) $upgrade->quoted_amount, - 'currency_code' => strtoupper((string) $upgrade->currency_code), - ], JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES)); + return $this->integrity->fingerprint($upgrade, $context); } private function reservationIntegrityError( ServiceUpgrade $upgrade, UpgradeReservation $reservation ): ?string { - $payload = $reservation->configuration_payload; - if (! is_array($payload)) { - return 'The paid upgrade reservation failed its immutable integrity check.'; - } - try { - $fingerprint = $this->reservationFingerprint($upgrade, $payload); + $upgrade->load([ + 'service.product.server.settings', + 'service.product.settings', + 'service.configs.configOption', + 'service.configs.configValue', + 'product.server.settings', + 'product.settings', + 'configs.configOption', + 'configs.configValue', + ]); + $this->assertProductPanel($upgrade->service); + $this->integrity->verifiedSnapshot($upgrade, $reservation); } catch (\Throwable) { return 'The paid upgrade reservation failed its immutable integrity check.'; } - $target = $payload['target'] ?? null; - $delta = $payload['delta'] ?? null; - if ( - ! is_array($target) - || ! is_array($delta) - || ! is_string($reservation->configuration_fingerprint) - || ! hash_equals( - $reservation->configuration_fingerprint, - $fingerprint - ) - || (int) $reservation->service_id - !== (int) $upgrade->service_id - || (int) $reservation->service_upgrade_id - !== (int) $upgrade->id - || (int) ($payload['service_upgrade_id'] ?? 0) - !== (int) $upgrade->id - || (string) ($payload['source_fingerprint'] ?? '') - !== (string) $upgrade->source_fingerprint - || (string) ($payload['target_fingerprint'] ?? '') - !== (string) $upgrade->target_fingerprint - || (string) ($payload['panel_identity'] ?? '') - !== (string) $reservation->panel_identity - || (int) ($payload['node_id'] ?? 0) - !== (int) $reservation->node_id - || (int) ($payload['location_id'] ?? 0) - !== (int) $reservation->location_id - || (int) ($payload['external_server_id'] ?? 0) - !== (int) $reservation->external_server_id - || (int) ($payload['external_user_id'] ?? 0) - !== (int) $reservation->external_user_id - || (string) ($payload['external_server_uuid'] ?? '') - !== (string) $reservation->external_server_uuid - || (string) ($payload['external_server_identifier'] ?? '') - !== (string) $reservation->external_server_identifier - || (int) ($target['memory'] ?? -1) - !== (int) $reservation->memory - || (int) ($target['cpu'] ?? -1) - !== (int) $reservation->cpu - || (int) ($target['disk'] ?? -1) - !== (int) $reservation->disk - || (int) ($delta['memory'] ?? -1) - !== (int) $reservation->reserved_memory - || (int) ($delta['cpu'] ?? -1) - !== (int) $reservation->reserved_cpu - || (int) ($delta['disk'] ?? -1) - !== (int) $reservation->reserved_disk - ) { - return 'The paid upgrade reservation failed its immutable integrity check.'; - } return null; } private function usesDynamicCapacity(ServiceUpgrade $upgrade): bool { - return $upgrade->service->product->usesDynamicResources() - || $upgrade->product->usesDynamicResources(); + return app(CapacityUpgradeReservationIdentity::class) + ->requiresCoordinator($upgrade); } /** diff --git a/database/migrations/2026_07_26_000030_enforce_one_checkout_commitment_per_service.php b/database/migrations/2026_07_26_000030_enforce_one_checkout_commitment_per_service.php index 3782ab2..96b8f24 100644 --- a/database/migrations/2026_07_26_000030_enforce_one_checkout_commitment_per_service.php +++ b/database/migrations/2026_07_26_000030_enforce_one_checkout_commitment_per_service.php @@ -11,6 +11,13 @@ public function up(): void { $driver = DB::getDriverName(); + // Never choose a winner between service-bound commitments. Two rows + // can represent different paid invoices, signed configurations, or + // external servers even when one appears more complete. Retiring one + // here would erase a financial/fulfillment obligation before the + // readiness gate can report it. + $this->assertNoDuplicateCheckoutCommitments(); + Schema::table('ptero_resource_reservations', function (Blueprint $table) { // service_id is SET NULL, so MariaDB cannot use it as the source of // a generated partial-unique column. Preserve an immutable guard. @@ -22,83 +29,6 @@ public function up(): void ->whereNull('service_guard_id') ->update(['service_guard_id' => DB::raw('service_id')]); - $activeStatuses = ['pending', 'paid_committed', 'confirmed']; - $duplicateGroups = DB::table('ptero_resource_reservations') - ->where('purpose', 'checkout') - ->whereNotNull('service_id') - ->whereIn('status', $activeStatuses) - ->get() - ->groupBy('service_id') - ->filter(fn ($rows) => $rows->count() > 1); - - foreach ($duplicateGroups as $serviceId => $rows) { - $externalIdentities = $rows - ->where('status', 'confirmed') - ->filter(fn ($row) => $row->external_server_id !== null || $row->external_server_uuid !== null) - ->map(fn ($row) => ($row->external_server_id ?? 'unknown') - .':' . ($row->external_server_uuid ?? 'unknown')) - ->unique() - ->values(); - if ($externalIdentities->count() > 1) { - throw new \RuntimeException( - "Service {$serviceId} has conflicting confirmed Pterodactyl identities; " - .'resolve them manually before running the durable-fulfillment migration.' - ); - } - - $ranked = $rows->sort(function ($left, $right): int { - $rank = static function ($row): int { - if ( - $row->status === 'confirmed' - && $row->external_server_id !== null - && $row->external_server_uuid !== null - ) { - return 4; - } - - return match ($row->status) { - 'confirmed' => 3, - 'paid_committed' => 2, - 'pending' => 1, - default => 0, - }; - }; - $status = $rank($right) <=> $rank($left); - if ($status !== 0) { - return $status; - } - - $leftFingerprint = $left->configuration_fingerprint !== null ? 1 : 0; - $rightFingerprint = $right->configuration_fingerprint !== null ? 1 : 0; - if ($leftFingerprint !== $rightFingerprint) { - return $rightFingerprint <=> $leftFingerprint; - } - - return (int) $right->id <=> (int) $left->id; - })->values(); - $retiredIds = $ranked->slice(1)->pluck('id'); - if ($retiredIds->isEmpty()) { - continue; - } - - DB::table('ptero_resource_reservations') - ->whereIn('id', $retiredIds) - ->update([ - 'status' => 'cancelled', - 'admin_notes' => 'Retired duplicate service commitment during durable-fulfillment migration.', - 'provisioning_started_at' => null, - 'provisioning_lease_id' => null, - 'updated_at' => now(), - ]); - DB::table('ptero_reservation_allocations') - ->whereIn('reservation_id', $retiredIds) - ->whereNull('released_at') - ->update([ - 'released_at' => now(), - 'updated_at' => now(), - ]); - } - if ($driver === 'sqlite') { DB::statement( 'CREATE UNIQUE INDEX ptero_reservations_active_checkout_service_unique ' @@ -148,4 +78,70 @@ public function down(): void }); } } + + /** + * Fail before adding/backfilling the guard column. This keeps a rejected + * migration retryable on databases where DDL auto-commits. + */ + private function assertNoDuplicateCheckoutCommitments(): void + { + $duplicateGroups = DB::table('ptero_resource_reservations') + ->where('purpose', 'checkout') + ->whereNotNull('service_id') + ->whereIn('status', [ + 'pending', + 'paid_committed', + 'confirmed', + ]) + ->orderBy('service_id') + ->orderBy('id') + ->get([ + 'id', + 'service_id', + 'status', + 'invoice_id', + 'configuration_fingerprint', + 'external_server_id', + 'external_server_uuid', + ]) + ->groupBy('service_id') + ->filter(fn ($rows) => $rows->count() > 1); + if ($duplicateGroups->isEmpty()) { + return; + } + + $details = $duplicateGroups + ->map(function ($rows, $serviceId): string { + $commitments = $rows + ->map(fn ($row): string => sprintf( + '#%d(status=%s, invoice=%s, fingerprint=%s, ' + .'external_server=%s, external_uuid=%s)', + (int) $row->id, + (string) $row->status, + $row->invoice_id !== null + ? (string) $row->invoice_id + : 'none', + is_string($row->configuration_fingerprint) + ? $row->configuration_fingerprint + : 'none', + $row->external_server_id !== null + ? (string) $row->external_server_id + : 'none', + is_string($row->external_server_uuid) + ? $row->external_server_uuid + : 'none' + )) + ->implode(', '); + + return "service {$serviceId}: {$commitments}"; + }) + ->implode('; '); + + throw new \RuntimeException( + 'Dynamic Pterodactyl found duplicate active checkout ' + .'commitments and refused to retire or release any obligation. ' + .'Reconcile every invoice, signed configuration, allocation, and ' + ."external server before rerunning the migration: {$details}" + ); + } }; diff --git a/migration-readiness.php b/migration-readiness.php index 685f583..7441e62 100644 --- a/migration-readiness.php +++ b/migration-readiness.php @@ -1,6 +1,11 @@ 0, + 'service_id' => null, + 'purpose' => 'schema', + 'missing' => ['table:ptero_resource_reservations'], + ]]; } $requiredColumns = [ + 'token', + 'idempotency_key', 'purpose', + 'status', + 'admin_notes', + 'cart_item_id', + 'cart_item_guard_id', + 'cart_id', 'configuration_fingerprint', 'configuration_payload', + 'service_id', + 'service_guard_id', + 'service_upgrade_id', + 'upgrade_guard_id', + 'server_extension_id', + 'panel_identity', + 'invoice_id', + 'user_id', + 'product_id', + 'plan_id', + 'quantity', + 'currency_code', + 'node_id', + 'location_id', + 'memory', + 'cpu', + 'disk', + 'reserved_memory', + 'reserved_cpu', + 'reserved_disk', + 'calculated_price', + 'pricing_breakdown', + 'pricing_version', + 'formula_version', + 'expires_at', + 'guaranteed_until', + 'paid_committed_at', + 'provisioning_started_at', + 'provisioning_lease_id', + 'provisioning_attempts', + 'last_provisioning_attempt_at', + 'next_provisioning_attempt_at', + 'last_provisioning_error', + 'consumed_at', + 'failure_alerted_at', + 'cancellation_requested_at', + 'last_cancellation_error', + 'cancellation_failure_alerted_at', 'external_server_id', 'external_user_id', 'external_server_uuid', 'external_server_identifier', + 'last_reconciled_at', + 'customer_notified_at', + 'product_stock_released_at', ]; foreach ($requiredColumns as $column) { if (! Schema::hasColumn('ptero_resource_reservations', $column)) { @@ -48,19 +111,188 @@ public function blockers(): array } } - return DB::table('ptero_resource_reservations') + $requiredTableColumns = [ + 'ptero_capacity_scopes' => [ + 'panel_identity', + 'location_id', + ], + 'ptero_reservation_allocations' => [ + 'reservation_id', + 'panel_identity', + 'node_id', + 'allocation_id', + 'ip', + 'port', + 'environment_key', + 'is_primary', + 'released_at', + ], + 'ptero_node_capacity_policies' => [ + 'panel_identity', + 'node_uuid', + 'node_id', + 'location_id', + 'cpu_capacity_percent', + 'cpu_overcommit_bps', + 'enabled', + ], + 'services' => [ + 'status', + 'product_id', + 'plan_id', + 'user_id', + 'quantity', + 'currency_code', + 'price', + 'product_stock_released_at', + ], + 'invoices' => [ + 'status', + 'user_id', + 'currency_code', + ], + 'invoice_items' => [ + 'invoice_id', + 'price', + 'quantity', + 'reference_type', + 'reference_id', + ], + 'service_configs' => [ + 'configurable_type', + 'configurable_id', + 'config_option_id', + 'config_value_id', + 'slider_value', + ], + 'properties' => [ + 'model_type', + 'model_id', + 'key', + 'value', + ], + 'settings' => [ + 'settingable_type', + 'settingable_id', + 'key', + 'value', + 'type', + ], + 'extensions' => [ + 'id', + 'type', + 'extension', + ], + 'products' => [ + 'id', + 'server_id', + ], + 'config_options' => [ + 'id', + 'parent_id', + 'type', + 'env_variable', + 'metadata', + ], + 'config_option_products' => [ + 'product_id', + 'config_option_id', + ], + ]; + foreach ($requiredTableColumns as $table => $columns) { + if (! Schema::hasTable($table)) { + return [[ + 'reservation_id' => 0, + 'service_id' => null, + 'purpose' => 'schema', + 'missing' => ["table:{$table}"], + ]]; + } + foreach ($columns as $column) { + if (! Schema::hasColumn($table, $column)) { + return [[ + 'reservation_id' => 0, + 'service_id' => null, + 'purpose' => 'schema', + 'missing' => ["column:{$table}.{$column}"], + ]]; + } + } + } + + if (! Schema::hasTable('service_upgrades')) { + return [[ + 'reservation_id' => 0, + 'service_id' => null, + 'purpose' => 'schema', + 'missing' => ['table:service_upgrades'], + ]]; + } + foreach ([ + 'service_id', + 'product_id', + 'plan_id', + 'invoice_id', + 'status', + 'active_service_guard_id', + 'source_snapshot', + 'target_snapshot', + 'source_fingerprint', + 'target_fingerprint', + 'quoted_amount', + 'currency_code', + 'completed_at', + ] as $column) { + if (! Schema::hasColumn('service_upgrades', $column)) { + return [[ + 'reservation_id' => 0, + 'service_id' => null, + 'purpose' => 'schema', + 'missing' => ["column:service_upgrades.{$column}"], + ]]; + } + } + + $blockers = DB::table('ptero_resource_reservations') ->where(function ($query): void { $query->where(function ($query): void { $query->where('purpose', 'checkout') + ->where(function ($query): void { + $query->where(function ($query): void { + $query->where('status', 'pending') + ->where(function ($query): void { + $query + ->whereNotNull('service_id') + ->orWhereNotNull( + 'service_guard_id' + ); + }); + })->orWhereIn('status', [ + 'paid_committed', + 'confirmed', + ]); + }); + })->orWhere(function ($query): void { + $query->where('purpose', 'upgrade') ->whereIn('status', [ 'pending', 'paid_committed', 'confirmed', - ]) - ->whereNotNull('service_id'); + ]); })->orWhere(function ($query): void { - $query->where('purpose', 'upgrade') - ->whereIn('status', ['pending', 'paid_committed']); + // Older checkout-identity and durable-fulfillment + // migrations could silently cancel a service-bound + // commitment before this gate ran. + $query->where('purpose', 'checkout') + ->where('status', 'cancelled') + ->where(function ($query): void { + $query->whereNotNull('service_id') + ->orWhereNotNull('service_guard_id'); + }) + ->whereIn( + 'admin_notes', + self::LEGACY_RETIREMENT_NOTES + ); }); }) ->orderBy('id') @@ -69,6 +301,10 @@ public function blockers(): array $missing = $reservation->purpose === 'upgrade' ? $this->missingUpgradeIdentity($reservation) : $this->missingCheckoutIdentity($reservation); + if ($this->wasBoundCommitmentRetired($reservation)) { + $missing[] = + 'legacy bound commitment was retired before readiness'; + } return [ 'reservation_id' => (int) $reservation->id, @@ -82,6 +318,12 @@ public function blockers(): array ->filter(fn (array $row): bool => $row['missing'] !== []) ->values() ->all(); + + return array_values(array_merge( + $blockers, + $this->missingDynamicServiceReservations(), + $this->missingActiveUpgradeReservations() + )); } public function assertReady(): void @@ -112,8 +354,8 @@ public function assertReady(): void } throw new \RuntimeException( - 'Dynamic Pterodactyl cannot finish upgrading because legacy ' - .'reservations lack immutable fulfillment identity: ' + 'Dynamic Pterodactyl cannot finish upgrading because its dynamic ' + .'stock schema or fulfillment proofs are incomplete: ' .implode('; ', $details) .'. Reconstruct the exact signed order configuration for every ' .'bound unpaid commitment. For provisioned services, also verify ' @@ -136,6 +378,9 @@ private function missingCheckoutIdentity(object $reservation): array foreach ([ 'server_extension_id', 'service_id', + 'service_guard_id', + 'cart_item_guard_id', + 'cart_id', 'user_id', 'product_id', 'plan_id', @@ -165,12 +410,39 @@ private function missingCheckoutIdentity(object $reservation): array $service = Service::query()->find($reservation->service_id); if ($service === null) { $missing[] = 'service'; - } elseif (! $this->checkoutPayloadMatchesService( - $payload, - $reservation, - $service - )) { - $missing[] = 'signed checkout/service identity agreement'; + } else { + if (! $this->checkoutPayloadMatchesService( + $payload, + $reservation, + $service + )) { + $missing[] = 'signed checkout/service identity agreement'; + } + if (! $this->checkoutLifecycleMatches( + $reservation, + $service + )) { + $missing[] = 'checkout service guard/lifecycle agreement'; + } + if (! $this->checkoutServiceResourcesMatch( + $payload, + $reservation, + $service + )) { + $missing[] = 'delivered service resource agreement'; + } + if (! $this->checkoutPricingMatches( + $payload, + $reservation + )) { + $missing[] = 'signed checkout pricing agreement'; + } + if (! $this->checkoutInvoiceMatches( + $reservation, + $service + )) { + $missing[] = 'checkout invoice/service billing agreement'; + } } $provisioning = $payload['provisioning_identity'] ?? null; @@ -204,6 +476,7 @@ private function missingCheckoutIdentity(object $reservation): array } foreach ([ 'panel_identity' => $reservation->panel_identity, + 'cart_id' => $reservation->cart_id, 'node_id' => $reservation->node_id, 'customer_id' => $reservation->user_id, 'product_id' => $reservation->product_id, @@ -221,13 +494,11 @@ private function missingCheckoutIdentity(object $reservation): array $missing[] = "configuration_payload.{$field}"; } } - if ($reservation->status !== 'confirmed') { - $this->requireActiveAllocationClaims( - $reservation, - $payload, - $missing - ); - } + $this->requireSignedAllocationClaims( + $reservation, + $payload, + $missing + ); return array_values(array_unique($missing)); } @@ -240,20 +511,35 @@ private function missingCheckoutIdentity(object $reservation): array * @param array $payload * @param list $missing */ - private function requireActiveAllocationClaims( + private function requireSignedAllocationClaims( object $reservation, array $payload, array &$missing ): void { + $claimRequirement = $reservation->status === 'confirmed' + ? 'released signed allocation claims' + : 'active signed allocation claims'; if (! Schema::hasTable('ptero_reservation_allocations')) { - $missing[] = 'active signed allocation claims'; + $missing[] = $claimRequirement; return; } $allocations = $payload['allocations'] ?? null; - if (! is_array($allocations) || $allocations === []) { - $missing[] = 'active signed allocation claims'; + $requiredCount = StrictInteger::parse( + data_get( + $payload, + 'allocation_requirements.required_count' + ) + ); + if ( + ! is_array($allocations) + || $allocations === [] + || $requiredCount === null + || $requiredCount <= 0 + || count($allocations) !== $requiredCount + ) { + $missing[] = $claimRequirement; return; } @@ -261,7 +547,7 @@ private function requireActiveAllocationClaims( $expected = []; foreach ($allocations as $allocation) { if (! is_array($allocation)) { - $missing[] = 'active signed allocation claims'; + $missing[] = $claimRequirement; return; } @@ -269,14 +555,24 @@ private function requireActiveAllocationClaims( $allocation['allocation_id'] ?? null ); $port = StrictInteger::parse($allocation['port'] ?? null); + $ip = $allocation['ip'] ?? null; + $environmentKey = $allocation['environment_key'] ?? null; + $isPrimary = $allocation['is_primary'] ?? null; if ( $allocationId === null || $allocationId <= 0 || $port === null || $port <= 0 || $port > 65535 + || ! is_string($ip) + || trim($ip) === '' + || ( + $environmentKey !== null + && ! is_string($environmentKey) + ) + || ! is_bool($isPrimary) ) { - $missing[] = 'active signed allocation claims'; + $missing[] = $claimRequirement; return; } @@ -284,12 +580,10 @@ private function requireActiveAllocationClaims( 'panel_identity' => (string) $reservation->panel_identity, 'node_id' => (int) $reservation->node_id, 'allocation_id' => $allocationId, - 'ip' => (string) ($allocation['ip'] ?? ''), + 'ip' => $ip, 'port' => $port, - 'environment_key' => - $allocation['environment_key'] ?? null, - 'is_primary' => - (bool) ($allocation['is_primary'] ?? false), + 'environment_key' => $environmentKey, + 'is_primary' => $isPrimary, ]; } usort( @@ -317,14 +611,463 @@ private function requireActiveAllocationClaims( if ( $expected !== $actual + || count(array_unique( + array_column($actual, 'allocation_id') + )) !== count($actual) || collect($actual)->where('is_primary', true)->count() !== 1 - || $claims->contains( - fn (object $allocation): bool => - $allocation->released_at !== null + || ( + $reservation->status === 'confirmed' + ? $claims->contains( + fn (object $allocation): bool => + $allocation->released_at === null + ) + : $claims->contains( + fn (object $allocation): bool => + $allocation->released_at !== null + ) + ) + ) { + $missing[] = $claimRequirement; + } + } + + private function wasBoundCommitmentRetired( + object $reservation + ): bool { + return $reservation->purpose === 'checkout' + && $reservation->status === 'cancelled' + && ( + $reservation->service_id !== null + || $reservation->service_guard_id !== null ) + && in_array( + $reservation->admin_notes, + self::LEGACY_RETIREMENT_NOTES, + true + ); + } + + /** + * A reservation-first scan cannot detect a dynamic service whose + * commitment was deleted, detached, or duplicated with a null guard. + * Inspect every non-cancelled capacity-backed service in reverse and + * require one lifecycle-coherent checkout commitment. + * + * @return list + * }> + */ + private function missingDynamicServiceReservations(): array + { + $historyServiceIds = DB::table('ptero_resource_reservations') + ->where('purpose', 'checkout') + ->whereNotNull('service_id') + ->distinct() + ->pluck('service_id') + ->map(fn ($id): int => (int) $id) + ->all(); + $dynamicProductIds = array_keys($this->rawDynamicProductIds()); + $configuredServiceIds = + $this->rawDynamicConfiguredServiceIds(); + if ( + $historyServiceIds === [] + && $dynamicProductIds === [] + && $configuredServiceIds === [] ) { - $missing[] = 'active signed allocation claims'; + return []; + } + + $services = Service::query() + ->where('status', '!=', Service::STATUS_CANCELLED) + ->where(function ($query) use ( + $historyServiceIds, + $dynamicProductIds, + $configuredServiceIds + ): void { + if ($historyServiceIds !== []) { + $query->whereIn('id', $historyServiceIds); + } + if ($configuredServiceIds !== []) { + $method = $historyServiceIds === [] + ? 'whereIn' + : 'orWhereIn'; + $query->{$method}('id', $configuredServiceIds); + } + if ($dynamicProductIds !== []) { + $method = $historyServiceIds === [] + && $configuredServiceIds === [] + ? 'whereIn' + : 'orWhereIn'; + $query->{$method}('product_id', $dynamicProductIds); + } + }) + ->orderBy('id') + ->get(); + if ($services->isEmpty()) { + return []; + } + + $history = DB::table('ptero_resource_reservations') + ->where('purpose', 'checkout') + ->whereIn('service_id', $services->modelKeys()) + ->orderBy('id') + ->get() + ->groupBy('service_id'); + $blockers = []; + + foreach ($services as $service) { + $reservations = $history + ->get($service->id, collect()) + ->whereIn('status', [ + 'pending', + 'paid_committed', + 'confirmed', + ]) + ->values(); + $expectedStatuses = $this->checkoutStatusesForService( + (string) $service->status + ); + $coherent = $expectedStatuses !== [] + && $reservations->count() === 1 + && in_array( + (string) $reservations->first()->status, + $expectedStatuses, + true + ) + && $this->checkoutLifecycleMatches( + $reservations->first(), + $service + ); + if ($coherent) { + continue; + } + + $blockers[] = [ + 'reservation_id' => $reservations->count() === 1 + ? (int) $reservations->first()->id + : 0, + 'service_id' => (int) $service->id, + 'purpose' => 'checkout', + 'missing' => [ + "dynamic service #{$service->id} requires exactly one " + .'lifecycle-coherent checkout capacity reservation', + ], + ]; + } + + return $blockers; + } + + /** + * A product or pivot may have been removed after a service was created. + * Its persisted dynamic ServiceConfig rows remain enough evidence that the + * service requires a capacity commitment. + * + * @return list + */ + private function rawDynamicConfiguredServiceIds(): array + { + $rows = DB::table('service_configs') + ->join( + 'config_options', + 'config_options.id', + '=', + 'service_configs.config_option_id' + ) + ->where( + 'service_configs.configurable_type', + Service::class + ) + ->where('config_options.type', 'dynamic_slider') + ->get([ + 'service_configs.configurable_id', + 'config_options.env_variable', + 'config_options.metadata', + ]); + $serviceIds = []; + foreach ($rows as $row) { + $metadata = is_string($row->metadata) + ? json_decode($row->metadata, true) + : (array) $row->metadata; + $resource = strtolower((string) ( + (is_array($metadata) + ? ($metadata['resource_type'] ?? null) + : null) + ?? $row->env_variable + ?? '' + )); + if (in_array($resource, ['memory', 'cpu', 'disk'], true)) { + $serviceIds[(int) $row->configurable_id] = true; + } + } + + return array_keys($serviceIds); + } + + /** + * Reservation-first scans cannot see an active dynamic ServiceUpgrade + * whose capacity row is missing, terminal, or duplicated. Inspect the + * core lifecycle in the reverse direction and require its one authoritative + * reservation before an extension upgrade may complete. + * + * @return list + * }> + */ + private function missingActiveUpgradeReservations(): array + { + $upgrades = ServiceUpgrade::query() + ->with([ + 'service.product', + 'product', + ]) + ->where(function ($query): void { + $query->whereIn('status', [ + ...ServiceUpgrade::activeStatuses(), + ServiceUpgrade::STATUS_COMPLETED, + ]) + ->orWhereNotNull('active_service_guard_id'); + }) + ->orderBy('id') + ->get(); + if ($upgrades->isEmpty()) { + return []; + } + + $history = DB::table('ptero_resource_reservations') + ->where('purpose', 'upgrade') + ->whereIn('service_upgrade_id', $upgrades->modelKeys()) + ->orderBy('id') + ->get() + ->groupBy('service_upgrade_id'); + $rawDynamicProducts = $this->rawDynamicProductIds(); + $rawPterodactylProducts = $this->rawPterodactylProductIds(); + $capacityBackedServices = DB::table( + 'ptero_resource_reservations' + ) + ->where('purpose', 'checkout') + ->whereNotNull('service_id') + ->pluck('service_id') + ->mapWithKeys( + fn ($id): array => [(int) $id => true] + ) + ->all(); + $dynamicCache = []; + $blockers = []; + + foreach ($upgrades as $upgrade) { + $rows = $history->get($upgrade->id, collect()); + $classificationFailed = false; + try { + $currentProduct = $upgrade->service?->product; + $targetProduct = $upgrade->product; + if ($currentProduct === null || $targetProduct === null) { + throw new \RuntimeException( + 'The active upgrade product identity is missing.' + ); + } + foreach ([$currentProduct, $targetProduct] as $product) { + $productId = (int) $product->id; + $dynamicCache[$productId] ??= + $product->usesDynamicResources(); + } + $dynamic = $rows->isNotEmpty() + || isset($capacityBackedServices[ + (int) $upgrade->service_id + ]) + || ($dynamicCache[(int) $currentProduct->id] ?? false) + || ($dynamicCache[(int) $targetProduct->id] ?? false) + || isset($rawDynamicProducts[(int) $currentProduct->id]) + || isset($rawDynamicProducts[(int) $targetProduct->id]) + || ( + ( + isset($rawPterodactylProducts[ + (int) $currentProduct->id + ]) + || isset($rawPterodactylProducts[ + (int) $targetProduct->id + ]) + ) + && $this->upgradeSnapshotsChangeOnlyResources( + $upgrade + ) + ); + } catch (\Throwable) { + $dynamic = true; + $classificationFailed = true; + } + if (! $dynamic) { + continue; + } + + $reservations = $rows->whereIn('status', [ + 'pending', + 'paid_committed', + 'confirmed', + ])->values(); + $expectedStatus = match ((string) $upgrade->status) { + ServiceUpgrade::STATUS_PENDING, + ServiceUpgrade::STATUS_AWAITING_PAYMENT => 'pending', + ServiceUpgrade::STATUS_PAID_COMMITTED, + ServiceUpgrade::STATUS_PROVISIONING, + ServiceUpgrade::STATUS_RETRYABLE_FAILED, + ServiceUpgrade::STATUS_NEEDS_ATTENTION => 'paid_committed', + ServiceUpgrade::STATUS_COMPLETED => 'confirmed', + default => null, + }; + $reservation = $reservations->count() === 1 + ? $reservations->first() + : null; + $reservationGuard = $reservation !== null + ? $this->positiveInteger( + $reservation->upgrade_guard_id ?? null + ) + : null; + $upgradeGuard = $this->positiveInteger( + $upgrade->active_service_guard_id + ); + if ( + ! $classificationFailed + && $expectedStatus !== null + && $reservations->count() === 1 + && $reservation?->status === $expectedStatus + && $this->upgradeLifecycleMatches( + (string) $reservation->status, + (string) $upgrade->status, + $reservationGuard, + $upgradeGuard, + (int) $upgrade->id, + (int) $upgrade->service_id, + $reservation->consumed_at ?? null, + $upgrade->completed_at + ) + ) { + continue; + } + + $blockers[] = [ + 'reservation_id' => $reservations->count() === 1 + ? (int) $reservations->first()->id + : 0, + 'service_id' => $upgrade->service_id !== null + ? (int) $upgrade->service_id + : null, + 'purpose' => 'upgrade', + 'missing' => [ + "dynamic service upgrade #{$upgrade->id} " + .'requires exactly one coherent capacity reservation', + ], + ]; + } + + return $blockers; + } + + /** + * Detect capacity-backed products without Eloquent soft-delete or current + * visibility scopes. A host or slider hidden after quote creation must not + * make an active dynamic upgrade disappear from readiness. + * + * @return array + */ + private function rawDynamicProductIds(): array + { + $rows = DB::table('config_options') + ->join( + 'config_option_products', + 'config_option_products.config_option_id', + '=', + 'config_options.id' + ) + ->join( + 'products', + 'products.id', + '=', + 'config_option_products.product_id' + ) + ->join( + 'extensions as server_extensions', + 'server_extensions.id', + '=', + 'products.server_id' + ) + ->where('config_options.type', 'dynamic_slider') + ->whereNull('config_options.parent_id') + ->where('server_extensions.type', 'server') + ->where('server_extensions.extension', 'Pterodactyl') + ->get([ + 'config_option_products.product_id', + 'config_options.env_variable', + 'config_options.metadata', + ]); + $products = []; + + foreach ($rows as $row) { + $metadata = is_string($row->metadata) + ? json_decode($row->metadata, true) + : (array) $row->metadata; + $resource = strtolower((string) ( + (is_array($metadata) + ? ($metadata['resource_type'] ?? null) + : null) + ?? $row->env_variable + ?? '' + )); + if (in_array($resource, ['memory', 'cpu', 'disk'], true)) { + $products[(int) $row->product_id] = true; + } + } + + return $products; + } + + /** + * @return array + */ + private function rawPterodactylProductIds(): array + { + return DB::table('products') + ->join( + 'extensions as server_extensions', + 'server_extensions.id', + '=', + 'products.server_id' + ) + ->where('server_extensions.type', 'server') + ->where('server_extensions.extension', 'Pterodactyl') + ->pluck('products.id') + ->mapWithKeys( + fn ($id): array => [(int) $id => true] + ) + ->all(); + } + + private function upgradeSnapshotsChangeOnlyResources( + ServiceUpgrade $upgrade + ): bool { + $source = $this->snapshotProperties( + $this->decodedArray($upgrade->source_snapshot) + ); + $target = $this->snapshotProperties( + $this->decodedArray($upgrade->target_snapshot) + ); + if ($source === null || $target === null) { + return false; } + + $sourceResources = $this->resourceVectorFromProperties($source); + $targetResources = $this->resourceVectorFromProperties($target); + + return $sourceResources !== null + && $targetResources !== null + && $sourceResources !== $targetResources + && $this->onlyResourcesChanged($source, $target); } /** @@ -345,37 +1088,72 @@ private function checkoutPayloadMatchesService( $eggId = is_array($provisioning) ? StrictInteger::parse($provisioning['egg_id'] ?? null) : null; + $customerId = StrictInteger::parse( + $payload['customer_id'] ?? null + ); + $serverExtensionId = StrictInteger::parse( + $payload['server_extension_id'] ?? null + ); + $productId = StrictInteger::parse( + $payload['product_id'] ?? null + ); + $planId = StrictInteger::parse($payload['plan_id'] ?? null); + $quantity = StrictInteger::parse($payload['quantity'] ?? null); + $memory = StrictInteger::parse( + data_get($payload, 'resources.memory') + ); + $cpu = StrictInteger::parse( + data_get($payload, 'resources.cpu') + ); + $disk = StrictInteger::parse( + data_get($payload, 'resources.disk') + ); + $locationId = StrictInteger::parse( + $payload['location_id'] ?? null + ); + $nodeId = StrictInteger::parse($payload['node_id'] ?? null); return (int) $reservation->service_id === (int) $service->id && (int) $reservation->user_id === (int) $service->user_id && (int) $reservation->product_id === (int) $service->product_id && (int) $reservation->plan_id === (int) $service->plan_id && (int) $reservation->quantity === (int) $service->quantity + && (int) $reservation->quantity === 1 && strtoupper((string) $reservation->currency_code) === strtoupper((string) $service->currency_code) - && (int) ($payload['customer_id'] ?? 0) + && $customerId !== null + && $customerId === (int) $reservation->user_id - && (int) ($payload['server_extension_id'] ?? 0) + && $serverExtensionId !== null + && $serverExtensionId === (int) $reservation->server_extension_id && (string) ($payload['panel_identity'] ?? '') === (string) $reservation->panel_identity - && (int) ($payload['product_id'] ?? 0) + && $productId !== null + && $productId === (int) $reservation->product_id - && (int) ($payload['plan_id'] ?? 0) + && $planId !== null + && $planId === (int) $reservation->plan_id - && (int) ($payload['quantity'] ?? 0) + && $quantity === 1 + && $quantity === (int) $reservation->quantity && strtoupper((string) ($payload['currency_code'] ?? '')) === strtoupper((string) $reservation->currency_code) - && (int) data_get($payload, 'resources.memory', 0) + && $memory !== null + && $memory === (int) $reservation->memory - && (int) data_get($payload, 'resources.cpu', 0) + && $cpu !== null + && $cpu === (int) $reservation->cpu - && (int) data_get($payload, 'resources.disk', 0) + && $disk !== null + && $disk === (int) $reservation->disk - && (int) ($payload['location_id'] ?? 0) + && $locationId !== null + && $locationId === (int) $reservation->location_id - && (int) ($payload['node_id'] ?? 0) + && $nodeId !== null + && $nodeId === (int) $reservation->node_id && $nestId !== null && $nestId > 0 @@ -387,45 +1165,431 @@ private function checkoutPayloadMatchesService( $provisioning['user_external_id'] ) && is_string($provisioning['user_email'] ?? null) - && trim($provisioning['user_email']) !== ''; + && trim($provisioning['user_email']) !== '' + && $this->productPanelMatchesCheckout( + $reservation + ); + } + + private function productPanelMatchesCheckout( + object $reservation + ): bool { + try { + $serverId = $this->positiveInteger( + $reservation->server_extension_id ?? null + ); + $server = $serverId !== null + ? Server::query() + ->with('settings') + ->find($serverId) + : null; + if ( + $server === null + || $server->extension !== 'Pterodactyl' + || ! is_string($reservation->panel_identity ?? null) + ) { + return false; + } + $settings = ExtensionHelper::settingsToArray( + $server->settings + ); + $panelIdentity = PanelEndpointIdentity::hash( + trim((string) ($settings['host'] ?? '')) + ); + } catch (\Throwable) { + return false; + } + + return hash_equals( + (string) $reservation->panel_identity, + $panelIdentity + ); } /** - * @param array $payload + * @return list */ - private function fingerprint(array $payload): string + private function checkoutStatusesForService(string $status): array { - return hash('sha256', json_encode( - $this->canonicalize($payload), - JSON_THROW_ON_ERROR - | JSON_PRESERVE_ZERO_FRACTION - | JSON_UNESCAPED_SLASHES - )); + return match ($status) { + Service::STATUS_PENDING => ['pending'], + Service::STATUS_PROVISIONING, + Service::STATUS_PROVISIONING_FAILED => ['paid_committed'], + Service::STATUS_ACTIVE, + Service::STATUS_SUSPENDED => ['confirmed'], + Service::STATUS_CANCELLATION_PENDING => [ + 'paid_committed', + 'confirmed', + ], + Service::STATUS_CANCELLED => ['confirmed'], + default => [], + }; + } + + private function checkoutLifecycleMatches( + object $reservation, + Service $service + ): bool { + $guard = $this->positiveInteger( + $reservation->service_guard_id ?? null + ); + $status = (string) ($reservation->status ?? ''); + $expectedStatuses = $this->checkoutStatusesForService( + (string) $service->status + ); + + $cancelledConfirmed = (string) $service->status + === Service::STATUS_CANCELLED + && $status === 'confirmed'; + $cancellationPending = (string) $service->status + === Service::STATUS_CANCELLATION_PENDING; + $stockReleaseMatches = $cancelledConfirmed + ? ($reservation->product_stock_released_at ?? null) !== null + && $service->product_stock_released_at !== null + : ($reservation->product_stock_released_at ?? null) === null + && $service->product_stock_released_at === null; + + return (int) ($reservation->service_id ?? 0) === (int) $service->id + && $guard === (int) $service->id + && in_array($status, $expectedStatuses, true) + && $stockReleaseMatches + && ( + ! $cancellationPending + || ($reservation->cancellation_requested_at ?? null) + !== null + ) + && ( + ! $cancelledConfirmed + || ( + ($reservation->cancellation_requested_at ?? null) + !== null + ) + ) + && ( + $status === 'confirmed' + ? ($reservation->consumed_at ?? null) !== null + : in_array( + $status, + ['pending', 'paid_committed'], + true + ) + && ($reservation->consumed_at ?? null) === null + ); } /** - * @param array $value - * @return array + * The signed resources must also be the values Paymenter's provisioner + * reads from the Service. A self-consistent reservation cannot authorize + * different mutable ServiceConfig values. + * + * @param array $payload */ - private function canonicalize(array $value): array - { - foreach ($value as $key => $item) { - if (is_array($item)) { - $value[$key] = $this->canonicalize($item); - } - } - if (! array_is_list($value)) { - ksort($value); + private function checkoutServiceResourcesMatch( + array $payload, + object $reservation, + Service $service + ): bool { + $properties = $this->currentServiceProperties($service); + $serviceResources = $this->resourceVectorFromProperties( + $properties + ); + $serviceLocation = $this->locationFromProperties($properties); + $payloadResources = $this->resourceVector( + $payload['resources'] ?? null + ); + $payloadLocation = StrictInteger::parse( + $payload['location_id'] ?? null + ); + $rowResources = $this->resourceVector([ + 'memory' => $reservation->memory ?? null, + 'cpu' => $reservation->cpu ?? null, + 'disk' => $reservation->disk ?? null, + ]); + $rowLocation = StrictInteger::parse( + $reservation->location_id ?? null + ); + + $immutableReservationMatches = $payloadResources !== null + && $payloadLocation !== null + && $rowResources !== null + && $rowLocation !== null + && $payloadResources === $rowResources + && $payloadLocation === $rowLocation; + if ( + ! $immutableReservationMatches + || $this->serviceHasCompletedUpgrade((int) $service->id) + ) { + return $immutableReservationMatches; } - return $value; + return $serviceResources !== null + && $serviceLocation !== null + && $serviceResources === $rowResources + && $serviceLocation === $rowLocation; } /** - * @return list + * @param array $payload */ - private function missingUpgradeIdentity(object $reservation): array - { + private function checkoutPricingMatches( + array $payload, + object $reservation + ): bool { + $configOptions = $payload['config_options'] ?? null; + if (! is_array($configOptions) || ! array_is_list($configOptions)) { + return false; + } + if (! $this->checkoutResourceOptionsMatch( + $payload, + $configOptions + )) { + return false; + } + + try { + $payloadAmount = $this->normalizedMoney( + $payload['calculated_price'] ?? null + ); + $reservationAmount = $this->normalizedMoney( + $reservation->calculated_price ?? null + ); + $pricingVersion = $this->fingerprint([ + 'product_id' => (int) $reservation->product_id, + 'plan_id' => (int) $reservation->plan_id, + 'currency_code' => strtoupper( + (string) $reservation->currency_code + ), + 'calculated_price' => $reservationAmount, + 'config_options' => $configOptions, + ]); + } catch (\Throwable) { + return false; + } + + return $reservationAmount[0] !== '-' + && $payloadAmount === $reservationAmount + && is_string($payload['pricing_version'] ?? null) + && hash_equals( + $pricingVersion, + $payload['pricing_version'] + ) + && is_string($reservation->pricing_version ?? null) + && hash_equals( + $pricingVersion, + (string) $reservation->pricing_version + ) + && ($payload['formula_version'] ?? null) + === 'dynamic-pterodactyl-v1' + && ($reservation->formula_version ?? null) + === 'dynamic-pterodactyl-v1'; + } + + /** + * @param array $payload + * @param list $configOptions + */ + private function checkoutResourceOptionsMatch( + array $payload, + array $configOptions + ): bool { + $payloadResources = $this->resourceVector( + $payload['resources'] ?? null + ); + if ($payloadResources === null) { + return false; + } + + $selected = []; + $optionIds = []; + foreach ($configOptions as $configOption) { + if (! is_array($configOption)) { + return false; + } + $resource = strtolower((string) ( + $configOption['resource_type'] ?? '' + )); + if (! in_array($resource, ['memory', 'cpu', 'disk'], true)) { + continue; + } + $optionId = $this->positiveInteger( + $configOption['id'] ?? null + ); + $value = StrictInteger::parse( + $configOption['value'] ?? null + ); + if ( + $optionId === null + || $value === null + || ($configOption['type'] ?? null) !== 'dynamic_slider' + || array_key_exists($resource, $selected) + || array_key_exists($optionId, $optionIds) + ) { + return false; + } + $selected[$resource] = $value; + $optionIds[$optionId] = $resource; + } + return ! ( + $selected === [] + || collect($selected)->contains( + fn (int $value, string $resource): bool => + $value !== $payloadResources[$resource] + ) + ); + } + + private function checkoutInvoiceMatches( + object $reservation, + Service $service + ): bool { + try { + $amount = $this->normalizedMoney( + $reservation->calculated_price ?? null + ); + } catch (\Throwable) { + return false; + } + if ($amount[0] === '-') { + return false; + } + if (! $this->moneyIsPositive($amount)) { + return ($reservation->invoice_id ?? null) === null; + } + + $invoiceId = $this->positiveInteger( + $reservation->invoice_id ?? null + ); + if ($invoiceId === null) { + return false; + } + $invoice = DB::table('invoices')->where('id', $invoiceId)->first(); + $reservationStatus = (string) ($reservation->status ?? ''); + if ( + $invoice === null + || (int) $invoice->user_id !== (int) $service->user_id + || strtoupper((string) $invoice->currency_code) + !== strtoupper((string) $service->currency_code) + || ( + $reservationStatus === 'pending' + ? (string) $invoice->status !== 'pending' + : (string) $invoice->status !== 'paid' + ) + ) { + return false; + } + + $items = DB::table('invoice_items') + ->where('invoice_id', $invoiceId) + ->where('reference_type', $service->getMorphClass()) + ->where('reference_id', $service->id) + ->orderBy('id') + ->get(); + if ($items->count() !== 1) { + return false; + } + $item = $items->first(); + + try { + $lineAmount = $this->normalizedMoney($item->price); + } catch (\Throwable) { + return false; + } + + return (int) $item->quantity === 1 + && (int) $reservation->quantity === 1 + && $lineAmount === $amount; + } + + /** + * @return array|null + */ + private function currentServiceProperties(Service $service): ?array + { + try { + $service->loadMissing([ + 'product.settings', + 'properties', + 'configs.configOption', + 'configs.configValue', + ]); + if ($service->product === null) { + return null; + } + $properties = array_merge( + ExtensionHelper::settingsToArray( + $service->product->settings + ), + ExtensionHelper::getServiceProperties($service) + ); + } catch (\Throwable) { + return null; + } + + $normalized = []; + foreach ($properties as $key => $value) { + $key = strtolower((string) $key); + if ($key === '' || array_key_exists($key, $normalized)) { + return null; + } + $normalized[$key] = $value; + } + ksort($normalized); + + return $normalized; + } + + private function serviceHasCompletedUpgrade(int $serviceId): bool + { + return ServiceUpgrade::query() + ->where('service_id', $serviceId) + ->where('status', ServiceUpgrade::STATUS_COMPLETED) + ->exists(); + } + + /** + * @param array $payload + */ + private function fingerprint(array $payload): string + { + return hash('sha256', json_encode( + $this->canonicalize($payload), + JSON_THROW_ON_ERROR + | JSON_PRESERVE_ZERO_FRACTION + | JSON_UNESCAPED_SLASHES + )); + } + + /** + * @param array $value + * @return array + */ + private function canonicalize(array $value): array + { + foreach ($value as $key => $item) { + if (is_array($item)) { + $value[$key] = $this->canonicalize($item); + } elseif ( + is_float($item) + && is_finite($item) + && floor($item) === $item + && $item >= PHP_INT_MIN + && $item <= PHP_INT_MAX + ) { + $value[$key] = (int) $item; + } + } + if (! array_is_list($value)) { + ksort($value); + } + + return $value; + } + + /** + * @return list + */ + private function missingUpgradeIdentity(object $reservation): array + { $missing = $this->missingCommonRemoteIdentity($reservation); $payload = $this->decodedPayload($reservation, $missing); if ($payload === null) { @@ -513,6 +1677,14 @@ private function missingUpgradeIdentity(object $reservation): array )) { $missing[] = 'valid configuration_fingerprint'; } + if ( + Schema::hasTable('ptero_reservation_allocations') + && DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservation->id) + ->exists() + ) { + $missing[] = 'unexpected checkout allocation claims'; + } return array_values(array_unique($missing)); } @@ -527,63 +1699,1050 @@ private function upgradeFingerprintMatches( object $reservation, array $payload ): bool { - $upgradeId = StrictInteger::parse( - $reservation->service_upgrade_id + $upgradeId = $this->positiveInteger( + $reservation->service_upgrade_id ?? null ); - if ($upgradeId === null || $upgradeId <= 0) { + if ($upgradeId === null) { + return false; + } + + try { + $upgrade = ServiceUpgrade::query() + ->with([ + 'service.product.server.settings', + 'service.product.settings', + 'service.plan', + 'service.configs.configOption', + 'service.configs.configValue', + 'service.user', + 'product.server.settings', + 'product.settings', + 'plan', + 'configs.configOption', + 'configs.configValue', + 'invoice', + ]) + ->find($upgradeId); + } catch (\Throwable) { + return false; + } + if ($upgrade === null || $upgrade->service === null) { return false; } - $upgrade = DB::table('service_upgrades')->find($upgradeId); - if ($upgrade === null) { + + $source = $this->resourceVector($payload['source'] ?? null); + $target = $this->resourceVector($payload['target'] ?? null); + $delta = $this->resourceVector($payload['delta'] ?? null); + $rowTarget = $this->resourceVector([ + 'memory' => $reservation->memory ?? null, + 'cpu' => $reservation->cpu ?? null, + 'disk' => $reservation->disk ?? null, + ]); + $rowDelta = $this->resourceVector([ + 'memory' => $reservation->reserved_memory ?? null, + 'cpu' => $reservation->reserved_cpu ?? null, + 'disk' => $reservation->reserved_disk ?? null, + ]); + $sourceSnapshot = $this->decodedArray( + $upgrade->source_snapshot + ); + $targetSnapshot = $this->decodedArray( + $upgrade->target_snapshot + ); + $sourceProperties = $this->snapshotProperties($sourceSnapshot); + $targetProperties = $this->snapshotProperties($targetSnapshot); + $snapshotSource = $this->resourceVectorFromProperties( + $sourceProperties + ); + $snapshotTarget = $this->resourceVectorFromProperties( + $targetProperties + ); + $snapshotLocation = $this->locationFromProperties( + $targetProperties + ); + $sourceSnapshotHash = $this->snapshotFingerprint($sourceSnapshot); + $targetSnapshotHash = $this->snapshotFingerprint($targetSnapshot); + $sourceFingerprint = $upgrade->source_fingerprint; + $targetFingerprint = $upgrade->target_fingerprint; + $upgradeServiceId = $this->positiveInteger($upgrade->service_id); + $upgradeProductId = $this->positiveInteger($upgrade->product_id); + $upgradePlanId = $this->positiveInteger($upgrade->plan_id); + $upgradeInvoiceId = $this->positiveInteger($upgrade->invoice_id); + $serviceUserId = $this->positiveInteger($upgrade->service->user_id); + $serviceProductId = $this->positiveInteger( + $upgrade->service->product_id + ); + $servicePlanId = $this->positiveInteger( + $upgrade->service->plan_id + ); + $serviceQuantity = StrictInteger::parse( + $upgrade->service->quantity + ); + $serviceCurrency = strtoupper( + (string) $upgrade->service->currency_code + ); + $productServerId = $this->positiveInteger( + $upgrade->product?->server_id + ); + $reservationServiceId = $this->positiveInteger( + $reservation->service_id ?? null + ); + $reservationUpgradeId = $this->positiveInteger( + $reservation->service_upgrade_id ?? null + ); + $reservationUserId = $this->positiveInteger( + $reservation->user_id ?? null + ); + $reservationProductId = $this->positiveInteger( + $reservation->product_id ?? null + ); + $reservationPlanId = $this->positiveInteger( + $reservation->plan_id ?? null + ); + $reservationInvoiceId = $this->positiveInteger( + $reservation->invoice_id ?? null + ); + $reservationServerId = $this->positiveInteger( + $reservation->server_extension_id ?? null + ); + $reservationQuantity = StrictInteger::parse( + $reservation->quantity ?? null + ); + $reservationGuard = $this->positiveInteger( + $reservation->upgrade_guard_id ?? null + ); + $upgradeGuard = $this->positiveInteger( + $upgrade->active_service_guard_id + ); + $payloadUpgradeId = $this->positiveInteger( + $payload['service_upgrade_id'] ?? null + ); + $nodeId = $this->positiveInteger($reservation->node_id ?? null); + $payloadNodeId = $this->positiveInteger( + $payload['node_id'] ?? null + ); + $locationId = $this->positiveInteger( + $reservation->location_id ?? null + ); + $payloadLocationId = $this->positiveInteger( + $payload['location_id'] ?? null + ); + $externalServerId = $this->positiveInteger( + $reservation->external_server_id ?? null + ); + $payloadExternalServerId = $this->positiveInteger( + $payload['external_server_id'] ?? null + ); + $externalUserId = $this->positiveInteger( + $reservation->external_user_id ?? null + ); + $payloadExternalUserId = $this->positiveInteger( + $payload['external_user_id'] ?? null + ); + $nestId = $this->positiveInteger($payload['nest_id'] ?? null); + $eggId = $this->positiveInteger($payload['egg_id'] ?? null); + $allocationId = $this->positiveInteger( + $payload['allocation_id'] ?? null + ); + $assignedAllocationIds = $this->positiveIntegerList( + $payload['assigned_allocation_ids'] ?? null + ); + $preservedBuild = $this->preservedBuild( + $payload['preserved_build'] ?? null + ); + $panelIdentity = $payload['panel_identity'] ?? null; + $externalServerUuid = $payload['external_server_uuid'] ?? null; + $externalServerIdentifier = + $payload['external_server_identifier'] ?? null; + $externalServerExternalId = + $payload['external_server_external_id'] ?? null; + $userExternalId = $payload['user_external_id'] ?? null; + $userEmail = $payload['user_email'] ?? null; + $reservationStatus = (string) ( + $reservation->status ?? '' + ); + + try { + $targetRecurring = StrictDecimal::parseNonNegative( + $targetSnapshot['recurring_price'] ?? null + ); + $targetRecurringAmount = $this->normalizedMoney( + $targetSnapshot['recurring_price'] ?? null + ); + $quotedAmount = $this->normalizedMoney( + $upgrade->quoted_amount + ); + $reservedAmount = $this->normalizedMoney( + $reservation->calculated_price ?? null + ); + $expectedFingerprint = $this->upgradeFingerprint( + $upgrade, + $payload + ); + $pricingVersion = $this->upgradePricingVersion($upgrade); + $invoiceMatches = $this->upgradeInvoiceMatches( + $upgrade, + (string) $reservation->status, + $quotedAmount, + $serviceUserId, + $serviceCurrency + ); + $upgrade->load([ + 'service.product.settings', + 'service.configs.configOption', + 'service.configs.configValue', + 'product.settings', + 'configs.configOption', + 'configs.configValue', + ]); + if ($reservationStatus === 'confirmed') { + if ($this->isLatestCompletedUpgrade($upgrade)) { + $liveTargetProperties = + $this->currentServiceProperties( + $upgrade->service + ); + $liveRecurringAmount = $this->normalizedMoney( + $upgrade->service->price + ); + } else { + // Historical completed upgrades are superseded by the + // next signed target. Only the latest target can equal + // the Service's current mutable state. + $liveTargetProperties = $targetProperties; + $liveRecurringAmount = $targetRecurringAmount; + } + } else { + $liveTargetProperties = $this->snapshotProperties([ + 'properties' => $upgrade->targetProperties(), + ]); + $liveRecurringAmount = $targetRecurringAmount; + } + $sourceStillMatches = ! in_array( + $reservationStatus, + ['pending', 'paid_committed'], + true + ) || $upgrade->sourceStillMatches(); + } catch (\Throwable) { return false; } + return $source !== null + && $target !== null + && $delta !== null + && $rowTarget !== null + && $rowDelta !== null + && $sourceSnapshot !== null + && $targetSnapshot !== null + && $sourceProperties !== null + && $targetProperties !== null + && $liveTargetProperties === $targetProperties + && $snapshotSource !== null + && $snapshotTarget !== null + && $snapshotLocation !== null + && $targetRecurring !== null + && $liveRecurringAmount === $targetRecurringAmount + && $sourceSnapshotHash !== null + && $targetSnapshotHash !== null + && is_string($sourceFingerprint) + && preg_match('/^[a-f0-9]{64}$/D', $sourceFingerprint) === 1 + && is_string($targetFingerprint) + && preg_match('/^[a-f0-9]{64}$/D', $targetFingerprint) === 1 + && hash_equals($sourceFingerprint, $sourceSnapshotHash) + && hash_equals($targetFingerprint, $targetSnapshotHash) + && $source === $snapshotSource + && $target === $snapshotTarget + && $source !== $target + && ! collect($target)->contains( + fn (int $value): bool => $value <= 0 + ) + && $target['disk'] >= $source['disk'] + && $this->onlyResourcesChanged( + $sourceProperties, + $targetProperties + ) + && $delta === [ + 'memory' => max(0, $target['memory'] - $source['memory']), + 'cpu' => max(0, $target['cpu'] - $source['cpu']), + 'disk' => max(0, $target['disk'] - $source['disk']), + ] + && ($reservation->purpose ?? null) === 'upgrade' + && $upgradeServiceId !== null + && $reservationServiceId === $upgradeServiceId + && $reservationUpgradeId === $upgradeId + && $payloadUpgradeId === $upgradeId + && $serviceUserId !== null + && $reservationUserId === $serviceUserId + && $serviceProductId !== null + && $upgradeProductId === $serviceProductId + && $reservationProductId === $serviceProductId + && $servicePlanId !== null + && $upgradePlanId === $servicePlanId + && $reservationPlanId === $servicePlanId + && $serviceQuantity === 1 + && $reservationQuantity === 1 + && $serviceCurrency !== '' + && strtoupper((string) $upgrade->currency_code) + === $serviceCurrency + && strtoupper((string) $reservation->currency_code) + === $serviceCurrency + && $this->snapshotIdentityMatches( + $sourceSnapshot, + $targetSnapshot, + $upgradeServiceId, + $serviceProductId, + $servicePlanId, + $serviceCurrency + ) + && ( + $upgrade->invoice_id === null + || $upgradeInvoiceId !== null + ) + && ( + ($reservation->invoice_id ?? null) === null + || $reservationInvoiceId !== null + ) + && $reservationInvoiceId === $upgradeInvoiceId + && ( + $this->moneyIsPositive($quotedAmount) + ? $upgradeInvoiceId !== null + : $upgradeInvoiceId === null + ) + && $invoiceMatches + && $productServerId !== null + && $reservationServerId === $productServerId + && $this->productPanelMatchesUpgrade( + $upgrade, + $reservation + ) + && ( + ($reservation->upgrade_guard_id ?? null) === null + || $reservationGuard !== null + ) + && ( + $upgrade->active_service_guard_id === null + || $upgradeGuard !== null + ) + && $quotedAmount === $reservedAmount + && (string) ($reservation->pricing_version ?? '') + === $pricingVersion + && (string) ($reservation->formula_version ?? '') + === 'dynamic-upgrade-v1' + && $this->upgradeLifecycleMatches( + (string) ($reservation->status ?? ''), + (string) $upgrade->status, + $reservationGuard, + $upgradeGuard, + $upgradeId, + $upgradeServiceId, + $reservation->consumed_at ?? null, + $upgrade->completed_at + ) + && $sourceStillMatches + && is_string($reservation->configuration_fingerprint) + && preg_match( + '/^[a-f0-9]{64}$/D', + $reservation->configuration_fingerprint + ) === 1 + && hash_equals( + $reservation->configuration_fingerprint, + $expectedFingerprint + ) + && (string) ($payload['source_fingerprint'] ?? '') + === $sourceFingerprint + && (string) ($payload['target_fingerprint'] ?? '') + === $targetFingerprint + && is_string($panelIdentity) + && preg_match('/^[a-f0-9]{64}$/D', $panelIdentity) === 1 + && is_string($reservation->panel_identity ?? null) + && hash_equals( + (string) $reservation->panel_identity, + $panelIdentity + ) + && $nodeId !== null + && $payloadNodeId === $nodeId + && $locationId !== null + && $payloadLocationId === $locationId + && $payloadLocationId === $snapshotLocation + && $externalServerId !== null + && $payloadExternalServerId === $externalServerId + && $externalUserId !== null + && $payloadExternalUserId === $externalUserId + && is_string($externalServerUuid) + && Str::isUuid($externalServerUuid) + && is_string($reservation->external_server_uuid ?? null) + && hash_equals( + (string) $reservation->external_server_uuid, + $externalServerUuid + ) + && is_string($externalServerIdentifier) + && trim($externalServerIdentifier) !== '' + && is_string( + $reservation->external_server_identifier ?? null + ) + && hash_equals( + (string) $reservation->external_server_identifier, + $externalServerIdentifier + ) + && is_string($externalServerExternalId) + && hash_equals( + (string) $upgradeServiceId, + $externalServerExternalId + ) + && is_string($userExternalId) + && hash_equals( + "paymenter-user-{$serviceUserId}", + $userExternalId + ) + && is_string($userEmail) + && trim($userEmail) !== '' + && $nestId !== null + && $eggId !== null + && $allocationId !== null + && $assignedAllocationIds !== null + && in_array($allocationId, $assignedAllocationIds, true) + && $preservedBuild !== null + && $target === $rowTarget + && $delta === $rowDelta + && $this->checkoutIdentityMatchesUpgrade( + $reservation, + $payload, + $upgradeServiceId + ); + } + + private function isLatestCompletedUpgrade( + ServiceUpgrade $upgrade + ): bool { + return (string) $upgrade->status === ServiceUpgrade::STATUS_COMPLETED + && ! ServiceUpgrade::query() + ->where('service_id', $upgrade->service_id) + ->where('status', ServiceUpgrade::STATUS_COMPLETED) + ->where('id', '>', $upgrade->id) + ->exists(); + } + + /** + * @return array|null + */ + private function decodedArray(mixed $value): ?array + { + if (is_array($value)) { + return $value; + } + if (! is_string($value) || trim($value) === '') { + return null; + } + try { - $expected = hash('sha256', json_encode([ - 'upgrade_id' => $upgradeId, - 'source_fingerprint' => (string) $upgrade->source_fingerprint, - 'target_fingerprint' => (string) $upgrade->target_fingerprint, - 'panel_identity' => $payload['panel_identity'] ?? null, - 'node_id' => $payload['node_id'] ?? null, - 'location_id' => $payload['location_id'] ?? null, + $decoded = json_decode( + $value, + true, + 512, + JSON_THROW_ON_ERROR + ); + } catch (\JsonException) { + return null; + } + + return is_array($decoded) ? $decoded : null; + } + + private function snapshotFingerprint(?array $snapshot): ?string + { + if ($snapshot === null) { + return null; + } + + try { + return hash('sha256', json_encode( + $this->canonicalizeUpgradeSnapshot($snapshot), + JSON_THROW_ON_ERROR + | JSON_PRESERVE_ZERO_FRACTION + | JSON_UNESCAPED_SLASHES + )); + } catch (\JsonException) { + return null; + } + } + + /** + * ServiceUpgrade deliberately preserves numeric representation while + * recursively sorting associative maps. Checkout fingerprints use the + * separate canonicalizer above, which normalizes integral JSON floats. + * + * @param array $value + * @return array + */ + private function canonicalizeUpgradeSnapshot(array $value): array + { + foreach ($value as $key => $item) { + if (is_array($item)) { + $value[$key] = $this->canonicalizeUpgradeSnapshot($item); + } + } + if (! array_is_list($value)) { + ksort($value); + } + + return $value; + } + + /** + * @param array|null $snapshot + * @return array|null + */ + private function snapshotProperties(?array $snapshot): ?array + { + $properties = $snapshot['properties'] ?? null; + if (! is_array($properties) || array_is_list($properties)) { + return null; + } + + $normalized = []; + foreach ($properties as $key => $value) { + $key = strtolower((string) $key); + if ($key === '' || array_key_exists($key, $normalized)) { + return null; + } + $normalized[$key] = $value; + } + ksort($normalized); + + return $normalized; + } + + /** + * @param array|null $properties + * @return array{memory: int, cpu: int, disk: int}|null + */ + private function resourceVectorFromProperties( + ?array $properties + ): ?array { + if ($properties === null) { + return null; + } + + $vector = []; + foreach (['memory', 'cpu', 'disk'] as $resource) { + $parsed = StrictInteger::parse( + $properties[$resource] ?? null + ) ?? StrictInteger::parseStoredDecimal( + $properties[$resource] ?? null + ); + if ($parsed === null || $parsed < 0) { + return null; + } + $vector[$resource] = $parsed; + } + + return $vector; + } + + /** + * @param array|null $properties + */ + private function locationFromProperties( + ?array $properties + ): ?int { + if ($properties === null) { + return null; + } + + $location = StrictInteger::parse( + $properties['location'] ?? null + ) ?? StrictInteger::parseStoredDecimal( + $properties['location'] ?? null + ); + if ($location !== null) { + return $location > 0 ? $location : null; + } + + $locationIds = $properties['location_ids'] ?? null; + if (is_string($locationIds)) { + $decoded = json_decode($locationIds, true); + $locationIds = json_last_error() === JSON_ERROR_NONE + && is_array($decoded) + ? $decoded + : [$locationIds]; + } elseif (! is_array($locationIds)) { + $locationIds = [$locationIds]; + } + if (! array_is_list($locationIds) || count($locationIds) !== 1) { + return null; + } + + $location = StrictInteger::parse($locationIds[0]) + ?? StrictInteger::parseStoredDecimal($locationIds[0]); + + return $location !== null && $location > 0 + ? $location + : null; + } + + /** + * @param array $source + * @param array $target + */ + private function onlyResourcesChanged( + array $source, + array $target + ): bool { + $keys = array_unique(array_merge( + array_keys($source), + array_keys($target) + )); + foreach ($keys as $key) { + if (in_array($key, ['memory', 'cpu', 'disk'], true)) { + continue; + } + if ( + ! array_key_exists($key, $source) + || ! array_key_exists($key, $target) + || $source[$key] !== $target[$key] + ) { + return false; + } + } + + return true; + } + + /** + * @param array $source + * @param array $target + */ + private function snapshotIdentityMatches( + array $source, + array $target, + int $serviceId, + int $productId, + int $planId, + string $currencyCode + ): bool { + return StrictInteger::parse($source['service_id'] ?? null) + === $serviceId + && StrictInteger::parse($target['service_id'] ?? null) + === $serviceId + && StrictInteger::parse($source['product_id'] ?? null) + === $productId + && StrictInteger::parse($target['product_id'] ?? null) + === $productId + && StrictInteger::parse($source['plan_id'] ?? null) + === $planId + && StrictInteger::parse($target['plan_id'] ?? null) + === $planId + && StrictInteger::parse($source['quantity'] ?? null) === 1 + && StrictInteger::parse($target['quantity'] ?? null) === 1 + && strtoupper((string) ($source['currency_code'] ?? '')) + === $currencyCode + && strtoupper((string) ($target['currency_code'] ?? '')) + === $currencyCode + && array_key_exists('billing_anchor', $source) + && array_key_exists('billing_anchor', $target) + && $source['billing_anchor'] === $target['billing_anchor']; + } + + private function upgradeLifecycleMatches( + string $reservationStatus, + string $upgradeStatus, + ?int $reservationGuard, + ?int $upgradeGuard, + int $upgradeId, + int $serviceId, + mixed $consumedAt, + mixed $completedAt + ): bool { + if ($reservationStatus === 'pending') { + return in_array( + $upgradeStatus, + [ + ServiceUpgrade::STATUS_PENDING, + ServiceUpgrade::STATUS_AWAITING_PAYMENT, + ], + true + ) + && $reservationGuard === $upgradeId + && $upgradeGuard === $serviceId + && $consumedAt === null + && $completedAt === null; + } + if ($reservationStatus === 'paid_committed') { + return in_array( + $upgradeStatus, + [ + ServiceUpgrade::STATUS_PAID_COMMITTED, + ServiceUpgrade::STATUS_PROVISIONING, + ServiceUpgrade::STATUS_RETRYABLE_FAILED, + ServiceUpgrade::STATUS_NEEDS_ATTENTION, + ], + true + ) + && $reservationGuard === $upgradeId + && $upgradeGuard === $serviceId + && $consumedAt === null + && $completedAt === null; + } + + return $reservationStatus === 'confirmed' + && $upgradeStatus === ServiceUpgrade::STATUS_COMPLETED + && $reservationGuard === null + && $upgradeGuard === null + && $consumedAt !== null + && $completedAt !== null; + } + + private function upgradeFingerprint( + ServiceUpgrade $upgrade, + array $payload + ): string { + return hash('sha256', json_encode( + $this->canonicalizeUpgradeSnapshot([ + 'upgrade_id' => (int) $upgrade->id, + 'source_fingerprint' => + (string) $upgrade->source_fingerprint, + 'target_fingerprint' => + (string) $upgrade->target_fingerprint, + 'panel_identity' => $payload['panel_identity'], + 'node_id' => $payload['node_id'], + 'location_id' => $payload['location_id'], 'external_server_id' => - $payload['external_server_id'] ?? null, + $payload['external_server_id'], 'external_server_uuid' => - $payload['external_server_uuid'] ?? null, + $payload['external_server_uuid'], 'external_server_identifier' => - $payload['external_server_identifier'] ?? null, + $payload['external_server_identifier'], 'external_server_external_id' => - $payload['external_server_external_id'] ?? null, - 'external_user_id' => - $payload['external_user_id'] ?? null, - 'user_external_id' => - $payload['user_external_id'] ?? null, - 'user_email' => $payload['user_email'] ?? null, - 'nest_id' => $payload['nest_id'] ?? null, - 'egg_id' => $payload['egg_id'] ?? null, - 'preserved_build' => - $payload['preserved_build'] ?? null, - 'allocation_id' => $payload['allocation_id'] ?? null, + $payload['external_server_external_id'], + 'external_user_id' => $payload['external_user_id'], + 'user_external_id' => $payload['user_external_id'], + 'user_email' => $payload['user_email'], + 'nest_id' => $payload['nest_id'], + 'egg_id' => $payload['egg_id'], + 'preserved_build' => $payload['preserved_build'], + 'allocation_id' => $payload['allocation_id'], 'assigned_allocation_ids' => - $payload['assigned_allocation_ids'] ?? null, - 'source' => $payload['source'] ?? null, - 'target' => $payload['target'] ?? null, - 'delta' => $payload['delta'] ?? null, - 'quoted_amount' => (string) $upgrade->quoted_amount, - 'currency_code' => strtoupper( - (string) $upgrade->currency_code + $payload['assigned_allocation_ids'], + 'source' => $payload['source'], + 'target' => $payload['target'], + 'delta' => $payload['delta'], + 'quoted_amount' => $this->normalizedMoney( + $upgrade->quoted_amount ), - ], JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES)); + 'currency_code' => + strtoupper((string) $upgrade->currency_code), + ]), + JSON_THROW_ON_ERROR + | JSON_PRESERVE_ZERO_FRACTION + | JSON_UNESCAPED_SLASHES + )); + } + + private function upgradePricingVersion( + ServiceUpgrade $upgrade + ): string { + return hash('sha256', json_encode([ + 'quoted_amount' => $this->normalizedMoney( + $upgrade->quoted_amount + ), + 'currency_code' => + strtoupper((string) $upgrade->currency_code), + ], JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES)); + } + + private function upgradeInvoiceMatches( + ServiceUpgrade $upgrade, + string $reservationStatus, + string $quotedAmount, + ?int $serviceUserId, + string $serviceCurrency + ): bool { + if (! $this->moneyIsPositive($quotedAmount)) { + return $upgrade->invoice_id === null; + } + + $invoice = $upgrade->invoice; + if ( + $invoice === null + || $serviceUserId === null + || (int) $invoice->user_id !== $serviceUserId + || strtoupper((string) $invoice->currency_code) + !== $serviceCurrency + || ( + $reservationStatus === 'pending' + ? $invoice->status !== 'pending' + : $invoice->status !== 'paid' + ) + ) { + return false; + } + + $items = $invoice->items() + ->orderBy('id') + ->get(); + if ($items->count() !== 1) { + return false; + } + $item = $items->first(); + + try { + $lineAmount = $this->normalizedMoney($item->price); + } catch (\Throwable) { + return false; + } + + return $item->reference_type === ServiceUpgrade::class + && (int) $item->reference_id === (int) $upgrade->id + && (int) $item->quantity === 1 + && $lineAmount === $quotedAmount; + } + + /** + * The upgrade is an in-place mutation of a server created by checkout. + * Re-prove the immutable server, panel, user, nest, and egg identity rather + * than trusting a self-consistent upgrade payload in isolation. + * + * @param array $payload + */ + private function checkoutIdentityMatchesUpgrade( + object $reservation, + array $payload, + int $serviceId + ): bool { + $checkout = DB::table('ptero_resource_reservations') + ->where('purpose', 'checkout') + ->where('service_id', $serviceId) + ->where('status', 'confirmed') + ->orderByDesc('id') + ->first(); + if ($checkout === null) { + return false; + } + + try { + $checkoutPayload = json_decode( + (string) $checkout->configuration_payload, + true, + 512, + JSON_THROW_ON_ERROR + ); } catch (\JsonException) { return false; } + if (! is_array($checkoutPayload)) { + return false; + } + $identity = $checkoutPayload['provisioning_identity'] ?? null; + if (! is_array($identity)) { + return false; + } + + $checkoutNest = $this->positiveInteger( + $identity['nest_id'] ?? null + ); + $checkoutEgg = $this->positiveInteger( + $identity['egg_id'] ?? null + ); + $checkoutUserExternalId = + $identity['user_external_id'] ?? null; + $checkoutUserEmail = $identity['user_email'] ?? null; + + return is_string($checkout->configuration_fingerprint) + && preg_match( + '/^[a-f0-9]{64}$/D', + $checkout->configuration_fingerprint + ) === 1 + && hash_equals( + $checkout->configuration_fingerprint, + $this->fingerprint($checkoutPayload) + ) + && (int) $checkout->service_id === $serviceId + && (int) $checkout->user_id === (int) $reservation->user_id + && (int) $checkout->product_id + === (int) $reservation->product_id + && (int) $checkout->plan_id === (int) $reservation->plan_id + && (int) $checkout->server_extension_id + === (int) $reservation->server_extension_id + && is_string($checkout->panel_identity) + && is_string($reservation->panel_identity ?? null) + && hash_equals( + $checkout->panel_identity, + (string) $reservation->panel_identity + ) + && (int) $checkout->external_server_id + === (int) $reservation->external_server_id + && (int) $checkout->external_user_id + === (int) $reservation->external_user_id + && is_string($checkout->external_server_uuid) + && is_string($reservation->external_server_uuid ?? null) + && hash_equals( + $checkout->external_server_uuid, + (string) $reservation->external_server_uuid + ) + && is_string($checkout->external_server_identifier) + && is_string( + $reservation->external_server_identifier ?? null + ) + && hash_equals( + $checkout->external_server_identifier, + (string) $reservation->external_server_identifier + ) + && $checkoutNest !== null + && $checkoutNest === $this->positiveInteger( + $payload['nest_id'] ?? null + ) + && $checkoutEgg !== null + && $checkoutEgg === $this->positiveInteger( + $payload['egg_id'] ?? null + ) + && is_string($checkoutUserExternalId) + && is_string($payload['user_external_id'] ?? null) + && hash_equals( + $checkoutUserExternalId, + $payload['user_external_id'] + ) + && is_string($checkoutUserEmail) + && is_string($payload['user_email'] ?? null) + && hash_equals( + strtolower(trim($checkoutUserEmail)), + strtolower(trim($payload['user_email'])) + ); + } + + private function productPanelMatchesUpgrade( + ServiceUpgrade $upgrade, + object $reservation + ): bool { + $server = $upgrade->product?->server; + if ( + $server === null + || $server->extension !== 'Pterodactyl' + || ! is_string($reservation->panel_identity ?? null) + ) { + return false; + } + + try { + $settings = ExtensionHelper::settingsToArray( + $server->settings + ); + $panelIdentity = PanelEndpointIdentity::hash( + trim((string) ($settings['host'] ?? '')) + ); + } catch (\Throwable) { + return false; + } return hash_equals( - (string) $reservation->configuration_fingerprint, - $expected + (string) $reservation->panel_identity, + $panelIdentity ); } + /** + * @return array{memory: int, cpu: int, disk: int}|null + */ + private function resourceVector(mixed $value): ?array + { + if (! is_array($value)) { + return null; + } + + $resources = []; + foreach (['memory', 'cpu', 'disk'] as $resource) { + $parsed = StrictInteger::parse($value[$resource] ?? null); + if ($parsed === null || $parsed < 0) { + return null; + } + $resources[$resource] = $parsed; + } + + return $resources; + } + + private function positiveInteger(mixed $value): ?int + { + $parsed = StrictInteger::parse($value); + + return $parsed !== null && $parsed > 0 ? $parsed : null; + } + + /** + * @return list|null + */ + private function positiveIntegerList(mixed $value): ?array + { + if (! is_array($value) || ! array_is_list($value)) { + return null; + } + + $normalized = []; + foreach ($value as $item) { + $parsed = $this->positiveInteger($item); + if ($parsed === null) { + return null; + } + $normalized[] = $parsed; + } + sort($normalized, SORT_NUMERIC); + + return $normalized !== [] + && count(array_unique($normalized)) === count($normalized) + ? $normalized + : null; + } + + /** + * @return array{ + * swap: int, + * io: int, + * threads: string|null, + * databases: int, + * allocations: int, + * backups: int + * }|null + */ + private function preservedBuild(mixed $value): ?array + { + if (! is_array($value)) { + return null; + } + + $threads = $value['threads'] ?? null; + $swap = StrictInteger::parse($value['swap'] ?? null); + $io = StrictInteger::parse($value['io'] ?? null); + $databases = StrictInteger::parse( + $value['databases'] ?? null + ); + $allocations = StrictInteger::parse( + $value['allocations'] ?? null + ); + $backups = StrictInteger::parse($value['backups'] ?? null); + if ( + ! array_key_exists('threads', $value) + || ($threads !== null && ! is_string($threads)) + || $swap === null + || $swap < 0 + || $io === null + || $io < 0 + || $databases === null + || $databases < 0 + || $allocations !== 0 + || $backups === null + || $backups < 0 + ) { + return null; + } + + return [ + 'swap' => $swap, + 'io' => $io, + 'threads' => $threads, + 'databases' => $databases, + 'allocations' => $allocations, + 'backups' => $backups, + ]; + } + /** * @param list $missing * @return array|null @@ -668,4 +2827,55 @@ private function requirePositive( $missing[] = $field; } } + + private function normalizedMoney(mixed $value): string + { + if (is_int($value)) { + $text = (string) $value; + } elseif (is_float($value) && is_finite($value)) { + $text = number_format($value, 2, '.', ''); + } elseif (is_string($value)) { + $text = $value; + } else { + throw new \UnexpectedValueException( + 'The upgrade quote amount is invalid.' + ); + } + + if ( + preg_match( + '/^(-?)(0|[1-9]\d*)(?:\.(\d+))?$/D', + $text, + $matches + ) !== 1 + ) { + throw new \UnexpectedValueException( + 'The upgrade quote amount is invalid.' + ); + } + + $fraction = $matches[3] ?? ''; + if ( + strlen($fraction) > 2 + && trim(substr($fraction, 2), '0') !== '' + ) { + throw new \UnexpectedValueException( + 'The upgrade quote amount exceeds cent precision.' + ); + } + + $fraction = str_pad(substr($fraction, 0, 2), 2, '0'); + $sign = ($matches[1] ?? '') === '-' + && ($matches[2] !== '0' || $fraction !== '00') + ? '-' + : ''; + + return $sign.$matches[2].'.'.$fraction; + } + + private function moneyIsPositive(string $amount): bool + { + return $amount[0] !== '-' + && $amount !== '0.00'; + } }; diff --git a/routes/api.php b/routes/api.php index ecf881a..a28299a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -13,16 +13,24 @@ use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\Admin\AdminCapacityController; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\Admin\AdminReservationController; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Middleware\EnsureUserIsAdmin; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\QuoteRateLimiterService; // Customer stock quote — guest-safe, CSRF-protected, and intentionally does // not expose node identity or other infrastructure detail. -Route::prefix('api/dynamic-pterodactyl')->middleware(['web', 'throttle:30,1'])->group(function () { +Route::prefix('api/dynamic-pterodactyl')->middleware([ + 'web', + 'throttle:'.QuoteRateLimiterService::NAME, +])->group(function () { Route::post('/products/{product}/resource-quote', ResourceQuoteController::class) ->whereNumber('product'); }); // Existing-service stock quotes are authenticated and customer-owned. -Route::prefix('api/dynamic-pterodactyl')->middleware(['web', 'auth', 'throttle:30,1'])->group(function () { +Route::prefix('api/dynamic-pterodactyl')->middleware([ + 'web', + 'auth', + 'throttle:'.QuoteRateLimiterService::NAME, +])->group(function () { Route::post('/services/{service}/upgrade-quote', UpgradeQuoteController::class); }); diff --git a/tests/Feature/LegacyReservationReadinessTest.php b/tests/Feature/LegacyReservationReadinessTest.php index 56c1423..01a5e3e 100644 --- a/tests/Feature/LegacyReservationReadinessTest.php +++ b/tests/Feature/LegacyReservationReadinessTest.php @@ -2,14 +2,22 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Feature; +use App\Models\ConfigOption; +use App\Models\ConfigOptionProduct; +use App\Models\Invoice; use App\Models\Plan; +use App\Models\Price; use App\Models\Product; use App\Models\Service; +use App\Models\ServiceUpgrade; +use App\Models\Server; use App\Models\User; +use App\Services\Service\CapacityServiceCreationCoordinator; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\DB; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\LegacyReservationReadinessService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationConfigurationService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\UpgradeReservationIntegrityService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; class LegacyReservationReadinessTest extends LaravelTestCase @@ -75,6 +83,217 @@ public function test_active_upgrade_without_immutable_identity_blocks_migration( ); } + public function test_complete_signed_upgrade_identity_passes_gate_across_decimal_materialization(): void + { + $this->insertCompleteUpgradeReservation(); + + (new LegacyReservationReadinessService)->assertReady(); + + $this->addToAssertionCount(1); + } + + public function test_upgrade_can_preserve_a_legitimate_new_node_and_allocation_identity(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + $reservation = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->first(); + $this->assertNotNull($reservation); + $upgrade = ServiceUpgrade::query() + ->findOrFail((int) $reservation->service_upgrade_id); + $payload = json_decode( + (string) $reservation->configuration_payload, + true, + 512, + JSON_THROW_ON_ERROR + ); + $payload['node_id'] = 8; + $payload['allocation_id'] = 8001; + $payload['assigned_allocation_ids'] = [8001, 8002]; + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'node_id' => 8, + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + 'configuration_fingerprint' => + (new UpgradeReservationIntegrityService) + ->fingerprint($upgrade, $payload), + 'updated_at' => now(), + ]); + + (new LegacyReservationReadinessService)->assertReady(); + + $this->addToAssertionCount(1); + } + + public function test_upgrade_resource_row_drift_blocks_migration(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update(['reserved_memory' => 0]); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $reservationId); + + $this->assertNotNull($blocker); + $this->assertContains( + 'valid configuration_fingerprint', + $blocker['missing'] + ); + } + + public function test_upgrade_price_version_drift_blocks_migration(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'pricing_version' => str_repeat('b', 64), + 'updated_at' => now(), + ]); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $reservationId); + + $this->assertNotNull($blocker); + $this->assertContains( + 'valid configuration_fingerprint', + $blocker['missing'] + ); + } + + public function test_upgrade_live_target_drift_blocks_migration(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + $upgradeId = $this->upgradeIdForReservation($reservationId); + $configId = DB::table('service_configs') + ->where('configurable_type', ServiceUpgrade::class) + ->where('configurable_id', $upgradeId) + ->orderBy('id') + ->value('id'); + $this->assertNotNull($configId); + DB::table('service_configs') + ->where('id', $configId) + ->update(['slider_value' => 16384]); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $reservationId); + + $this->assertNotNull($blocker); + $this->assertContains( + 'valid configuration_fingerprint', + $blocker['missing'] + ); + } + + public function test_upgrade_source_billing_anchor_drift_blocks_migration(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + $serviceId = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('service_id'); + $this->assertNotNull($serviceId); + DB::table('services') + ->where('id', $serviceId) + ->update([ + 'expires_at' => now()->addMonths(2), + 'updated_at' => now(), + ]); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $reservationId); + + $this->assertNotNull($blocker); + $this->assertContains( + 'valid configuration_fingerprint', + $blocker['missing'] + ); + } + + public function test_active_dynamic_upgrade_missing_reservation_blocks_migration(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + $upgradeId = $this->upgradeIdForReservation($reservationId); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->delete(); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->first( + fn (array $row): bool => + $row['purpose'] === 'upgrade' + && in_array( + "dynamic service upgrade #{$upgradeId} " + .'requires exactly one coherent capacity reservation', + $row['missing'], + true + ) + ); + + $this->assertNotNull($blocker); + $this->assertSame(0, $blocker['reservation_id']); + } + + public function test_upgrade_lifecycle_status_drift_blocks_migration(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + $upgradeId = $this->upgradeIdForReservation($reservationId); + DB::table('service_upgrades') + ->where('id', $upgradeId) + ->update([ + 'status' => ServiceUpgrade::STATUS_PAID_COMMITTED, + 'updated_at' => now(), + ]); + + $blockers = collect( + (new LegacyReservationReadinessService)->blockers() + ); + $this->assertTrue( + $blockers->contains( + fn (array $row): bool => + $row['purpose'] === 'upgrade' + && in_array( + "dynamic service upgrade #{$upgradeId} " + .'requires exactly one coherent capacity reservation', + $row['missing'], + true + ) + ) + ); + } + + public function test_upgrade_snapshot_loss_blocks_migration(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + $upgradeId = $this->upgradeIdForReservation($reservationId); + DB::table('service_upgrades') + ->where('id', $upgradeId) + ->update([ + 'target_snapshot' => null, + 'target_fingerprint' => null, + 'updated_at' => now(), + ]); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $reservationId); + + $this->assertNotNull($blocker); + $this->assertContains( + 'valid configuration_fingerprint', + $blocker['missing'] + ); + } + public function test_bound_unpaid_checkout_without_signed_snapshot_blocks_migration(): void { $service = $this->service(); @@ -101,47 +320,198 @@ public function test_bound_unpaid_checkout_without_signed_snapshot_blocks_migrat ); } + public function test_service_bound_commitment_retired_by_legacy_migration_still_blocks_readiness(): void + { + $service = $this->service(); + $reservationId = $this->insertReservation($service, [ + 'status' => 'cancelled', + 'configuration_fingerprint' => null, + 'configuration_payload' => null, + 'admin_notes' => + 'Retired during migration to server-owned reservations.', + ]); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $reservationId); + + $this->assertNotNull($blocker); + $this->assertContains( + 'legacy bound commitment was retired before readiness', + $blocker['missing'] + ); + } + + public function test_duplicate_commitment_retired_by_old_durable_migration_still_blocks_readiness(): void + { + $fixture = $this->insertCompleteCheckoutReservation(); + $retiredId = $this->duplicateReservation( + $fixture['reservation_id'], + [ + 'status' => 'cancelled', + 'admin_notes' => + 'Retired duplicate service commitment during ' + .'durable-fulfillment migration.', + ] + ); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $retiredId); + + $this->assertNotNull($blocker); + $this->assertContains( + 'legacy bound commitment was retired before readiness', + $blocker['missing'] + ); + } + + public function test_checkout_commitment_migration_refuses_duplicate_paid_obligations_without_mutation(): void + { + $fixture = $this->insertCompleteCheckoutReservation( + status: 'paid_committed' + ); + $secondInvoice = Invoice::factory()->create([ + 'user_id' => $fixture['service']->user_id, + 'currency_code' => 'USD', + 'status' => Invoice::STATUS_PAID, + ]); + $duplicateId = $this->duplicateReservation( + $fixture['reservation_id'], + [ + 'service_guard_id' => null, + 'invoice_id' => $secondInvoice->id, + 'configuration_fingerprint' => str_repeat('b', 64), + ] + ); + $this->insertAllocation( + $duplicateId, + $fixture['panel'], + released: false, + allocationId: 7002 + ); + + try { + $this->invokeCheckoutCommitmentPreflight(); + $this->fail( + 'Expected duplicate paid checkout commitments to block ' + .'the migration.' + ); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'refused to retire or release any obligation', + $exception->getMessage() + ); + $this->assertStringContainsString( + "service {$fixture['service']->id}", + $exception->getMessage() + ); + $this->assertStringContainsString( + "#{$fixture['reservation_id']}", + $exception->getMessage() + ); + $this->assertStringContainsString( + "#{$duplicateId}", + $exception->getMessage() + ); + } + + $this->assertSame( + ['paid_committed', 'paid_committed'], + DB::table('ptero_resource_reservations') + ->whereIn('id', [ + $fixture['reservation_id'], + $duplicateId, + ]) + ->orderBy('id') + ->pluck('status') + ->all() + ); + $this->assertSame( + 0, + DB::table('ptero_reservation_allocations') + ->whereIn('reservation_id', [ + $fixture['reservation_id'], + $duplicateId, + ]) + ->whereNotNull('released_at') + ->count() + ); + } + + public function test_checkout_commitment_migration_preserves_upgrade_history(): void + { + $upgradeReservationId = + $this->insertCompleteUpgradeReservation(); + + $this->invokeCheckoutCommitmentPreflight(); + + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $upgradeReservationId, + 'purpose' => 'upgrade', + 'status' => 'pending', + ]); + } + public function test_complete_signed_checkout_identity_passes_gate(): void + { + $this->insertCompleteCheckoutReservation(); + + (new LegacyReservationReadinessService)->assertReady(); + + $this->addToAssertionCount(1); + } + + public function test_paid_committed_checkout_matches_provisioning_service_lifecycle(): void + { + $this->insertCompleteCheckoutReservation( + status: 'paid_committed' + ); + + (new LegacyReservationReadinessService)->assertReady(); + + $this->addToAssertionCount(1); + } + + public function test_cancelled_service_preserves_its_confirmed_fulfillment_tombstone(): void + { + $fixture = $this->insertCompleteCheckoutReservation(); + DB::table('services') + ->where('id', $fixture['service']->id) + ->update([ + 'status' => Service::STATUS_CANCELLED, + 'product_stock_released_at' => now(), + 'updated_at' => now(), + ]); + DB::table('ptero_resource_reservations') + ->where('id', $fixture['reservation_id']) + ->update([ + 'cancellation_requested_at' => now(), + 'product_stock_released_at' => now(), + 'updated_at' => now(), + ]); + + (new LegacyReservationReadinessService)->assertReady(); + + $this->addToAssertionCount(1); + } + + public function test_fractional_resource_identity_cannot_pass_readiness_by_integer_truncation(): void { $service = $this->service(); $panel = hash('sha256', 'https://panel.example.com'); - $payload = [ - 'customer_id' => $service->user_id, - 'server_extension_id' => 41, - 'panel_identity' => $panel, - 'product_id' => $service->product_id, - 'plan_id' => $service->plan_id, - 'quantity' => 1, - 'currency_code' => 'USD', - 'resources' => [ - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 20480, - ], - 'location_id' => 3, - 'node_id' => 7, - 'provisioning_identity' => [ - 'nest_id' => 1, - 'egg_id' => 2, - 'user_external_id' => - "paymenter-user-{$service->user_id}", - 'user_email' => (string) $service->user->email, - ], - 'allocations' => [[ - 'allocation_id' => 7001, - 'ip' => '192.0.2.10', - 'port' => 25565, - 'environment_key' => 'SERVER_PORT', - 'is_primary' => true, - ]], - ]; - $fingerprint = (new ReservationConfigurationService) - ->fingerprint($payload); - $this->insertReservation($service, [ + $payload = $this->completeCheckoutPayload( + $service, + $panel, + memory: 4096.5 + ); + $reservationId = $this->insertReservation($service, [ 'status' => 'confirmed', 'server_extension_id' => 41, 'panel_identity' => $panel, - 'configuration_fingerprint' => $fingerprint, + 'configuration_fingerprint' => + (new ReservationConfigurationService) + ->fingerprint($payload), 'configuration_payload' => json_encode( $payload, JSON_THROW_ON_ERROR @@ -152,59 +522,70 @@ public function test_complete_signed_checkout_identity_passes_gate(): void '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', 'external_server_identifier' => 'server-71', ]); + $this->insertReleasedAllocation($reservationId, $panel); - (new LegacyReservationReadinessService)->assertReady(); + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $reservationId); - $this->addToAssertionCount(1); + $this->assertNotNull($blocker); + $this->assertContains( + 'signed checkout/service identity agreement', + $blocker['missing'] + ); } - public function test_bound_unpaid_checkout_requires_materialized_allocation_claims(): void + public function test_quantity_above_one_cannot_pass_legacy_readiness(): void { $service = $this->service(); + DB::table('services')->where('id', $service->id)->update([ + 'quantity' => 2, + ]); + $service->refresh(); $panel = hash('sha256', 'https://panel.example.com'); - $payload = [ - 'customer_id' => $service->user_id, - 'server_extension_id' => 41, - 'panel_identity' => $panel, - 'product_id' => $service->product_id, - 'plan_id' => $service->plan_id, - 'quantity' => 1, - 'currency_code' => 'USD', - 'resources' => [ - 'memory' => 4096, - 'cpu' => 200, - 'disk' => 20480, - ], - 'location_id' => 3, - 'node_id' => 7, - 'provisioning_identity' => [ - 'nest_id' => 1, - 'egg_id' => 2, - 'user_external_id' => - "paymenter-user-{$service->user_id}", - 'user_email' => (string) $service->user->email, - ], - 'allocations' => [[ - 'allocation_id' => 7001, - 'ip' => '192.0.2.10', - 'port' => 25565, - 'environment_key' => 'SERVER_PORT', - 'is_primary' => true, - ]], - ]; - $fingerprint = (new ReservationConfigurationService) - ->fingerprint($payload); + $payload = $this->completeCheckoutPayload( + $service, + $panel, + quantity: 2 + ); $reservationId = $this->insertReservation($service, [ - 'status' => 'pending', + 'status' => 'confirmed', + 'quantity' => 2, 'server_extension_id' => 41, 'panel_identity' => $panel, - 'configuration_fingerprint' => $fingerprint, + 'configuration_fingerprint' => + (new ReservationConfigurationService) + ->fingerprint($payload), 'configuration_payload' => json_encode( $payload, JSON_THROW_ON_ERROR ), - 'consumed_at' => null, + 'external_server_id' => 71, + 'external_user_id' => 44, + 'external_server_uuid' => + '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', + 'external_server_identifier' => 'server-71', ]); + $this->insertReleasedAllocation($reservationId, $panel); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $reservationId); + + $this->assertNotNull($blocker); + $this->assertContains( + 'signed checkout/service identity agreement', + $blocker['missing'] + ); + } + + public function test_bound_unpaid_checkout_requires_materialized_allocation_claims(): void + { + $fixture = $this->insertCompleteCheckoutReservation( + status: 'pending', + withAllocation: false + ); + $reservationId = $fixture['reservation_id']; $blockers = (new LegacyReservationReadinessService)->blockers(); $blocker = collect($blockers)->firstWhere( @@ -218,23 +599,352 @@ public function test_bound_unpaid_checkout_requires_materialized_allocation_clai $blocker['missing'] ); - DB::table('ptero_reservation_allocations')->insert([ - 'reservation_id' => $reservationId, - 'panel_identity' => $panel, - 'node_id' => 7, - 'allocation_id' => 7001, - 'ip' => '192.0.2.10', - 'port' => 25565, - 'environment_key' => 'SERVER_PORT', - 'is_primary' => true, - 'created_at' => now(), + $this->insertAllocation( + $reservationId, + $fixture['panel'], + released: false + ); + + (new LegacyReservationReadinessService)->assertReady(); + $this->addToAssertionCount(1); + } + + public function test_dynamic_service_missing_checkout_reservation_blocks_reverse_scan(): void + { + $fixture = $this->insertCompleteCheckoutReservation(); + DB::table('ptero_resource_reservations') + ->where('id', $fixture['reservation_id']) + ->delete(); + + $this->assertTrue( + collect( + (new LegacyReservationReadinessService)->blockers() + )->contains( + fn (array $row): bool => + $row['purpose'] === 'checkout' + && $row['service_id'] === $fixture['service']->id + && in_array( + "dynamic service #{$fixture['service']->id} " + .'requires exactly one lifecycle-coherent ' + .'checkout capacity reservation', + $row['missing'], + true + ) + ) + ); + } + + public function test_duplicate_checkout_reservations_block_reverse_scan_even_without_second_guard(): void + { + $fixture = $this->insertCompleteCheckoutReservation(); + $duplicateId = $this->duplicateReservation( + $fixture['reservation_id'], + [ + 'service_guard_id' => null, + ] + ); + $this->insertAllocation( + $duplicateId, + $fixture['panel'], + released: true + ); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->first( + fn (array $row): bool => + $row['purpose'] === 'checkout' + && $row['reservation_id'] === 0 + && $row['service_id'] === $fixture['service']->id + ); + + $this->assertNotNull($blocker); + $this->assertStringContainsString( + 'exactly one lifecycle-coherent checkout', + implode(', ', $blocker['missing']) + ); + } + + public function test_checkout_consumed_lifecycle_drift_blocks_readiness(): void + { + $fixture = $this->insertCompleteCheckoutReservation(); + DB::table('ptero_resource_reservations') + ->where('id', $fixture['reservation_id']) + ->update([ + 'consumed_at' => null, + 'updated_at' => now(), + ]); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $fixture['reservation_id']); + + $this->assertNotNull($blocker); + $this->assertContains( + 'checkout service guard/lifecycle agreement', + $blocker['missing'] + ); + } + + public function test_checkout_service_guard_drift_blocks_readiness(): void + { + $fixture = $this->insertCompleteCheckoutReservation(); + DB::table('ptero_resource_reservations') + ->where('id', $fixture['reservation_id']) + ->update([ + 'service_guard_id' => null, + 'updated_at' => now(), + ]); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $fixture['reservation_id']); + + $this->assertNotNull($blocker); + $this->assertContains( + 'checkout service guard/lifecycle agreement', + $blocker['missing'] + ); + } + + public function test_checkout_live_service_resource_drift_blocks_readiness(): void + { + $fixture = $this->insertCompleteCheckoutReservation(); + $memoryOption = DB::table('config_options') + ->where('env_variable', 'memory') + ->whereExists(function ($query) use ($fixture): void { + $query->selectRaw('1') + ->from('config_option_products') + ->whereColumn( + 'config_option_products.config_option_id', + 'config_options.id' + ) + ->where( + 'config_option_products.product_id', + $fixture['service']->product_id + ); + }) + ->value('id'); + $this->assertNotNull($memoryOption); + DB::table('service_configs') + ->where('configurable_type', Service::class) + ->where('configurable_id', $fixture['service']->id) + ->where('config_option_id', $memoryOption) + ->update([ + 'slider_value' => 8192, + 'updated_at' => now(), + ]); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $fixture['reservation_id']); + + $this->assertNotNull($blocker); + $this->assertContains( + 'delivered service resource agreement', + $blocker['missing'] + ); + } + + public function test_checkout_price_version_drift_blocks_readiness(): void + { + $fixture = $this->insertCompleteCheckoutReservation(); + DB::table('ptero_resource_reservations') + ->where('id', $fixture['reservation_id']) + ->update([ + 'pricing_version' => str_repeat('b', 64), + 'updated_at' => now(), + ]); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $fixture['reservation_id']); + + $this->assertNotNull($blocker); + $this->assertContains( + 'signed checkout pricing agreement', + $blocker['missing'] + ); + } + + public function test_checkout_invoice_line_drift_blocks_readiness(): void + { + $fixture = $this->insertCompleteCheckoutReservation(); + DB::table('invoice_items') + ->where('invoice_id', $fixture['invoice_id']) + ->where('reference_type', Service::class) + ->where('reference_id', $fixture['service']->id) + ->update([ + 'price' => '9.00', + 'updated_at' => now(), + ]); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $fixture['reservation_id']); + + $this->assertNotNull($blocker); + $this->assertContains( + 'checkout invoice/service billing agreement', + $blocker['missing'] + ); + } + + public function test_completed_upgrade_missing_reservation_blocks_reverse_scan(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + $this->completeUpgrade($reservationId, applyTarget: true); + $upgradeId = $this->upgradeIdForReservation($reservationId); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->delete(); + + $this->assertTrue( + collect( + (new LegacyReservationReadinessService)->blockers() + )->contains( + fn (array $row): bool => + $row['purpose'] === 'upgrade' + && in_array( + "dynamic service upgrade #{$upgradeId} " + .'requires exactly one coherent capacity ' + .'reservation', + $row['missing'], + true + ) + ) + ); + } + + public function test_completed_upgrade_duplicate_reservations_block_reverse_scan(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + $this->completeUpgrade($reservationId, applyTarget: true); + $upgradeId = $this->upgradeIdForReservation($reservationId); + $this->duplicateReservation($reservationId); + + $this->assertTrue( + collect( + (new LegacyReservationReadinessService)->blockers() + )->contains( + fn (array $row): bool => + $row['purpose'] === 'upgrade' + && $row['reservation_id'] === 0 + && in_array( + "dynamic service upgrade #{$upgradeId} " + .'requires exactly one coherent capacity ' + .'reservation', + $row['missing'], + true + ) + ) + ); + } + + public function test_confirmed_upgrade_not_applied_to_service_blocks_readiness(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + $this->completeUpgrade($reservationId, applyTarget: false); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $reservationId); + + $this->assertNotNull($blocker); + $this->assertContains( + 'valid configuration_fingerprint', + $blocker['missing'] + ); + } + + public function test_confirmed_upgrade_recurring_price_drift_blocks_readiness(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + $this->completeUpgrade($reservationId, applyTarget: true); + $serviceId = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('service_id'); + $this->assertNotNull($serviceId); + DB::table('services')->where('id', $serviceId)->update([ + 'price' => '1.00', 'updated_at' => now(), ]); + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $reservationId); + + $this->assertNotNull($blocker); + $this->assertContains( + 'valid configuration_fingerprint', + $blocker['missing'] + ); + } + + public function test_completed_upgrade_with_applied_target_passes_readiness(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + $this->completeUpgrade($reservationId, applyTarget: true); + (new LegacyReservationReadinessService)->assertReady(); + $this->addToAssertionCount(1); } + public function test_upgrade_source_and_target_billing_anchors_must_match(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + $upgradeId = $this->upgradeIdForReservation($reservationId); + $upgrade = ServiceUpgrade::query()->findOrFail($upgradeId); + $target = (array) $upgrade->target_snapshot; + $target['billing_anchor']['stored_recurring_price'] = '999.00'; + $targetFingerprint = $this->upgradeSnapshotFingerprint($target); + DB::table('service_upgrades') + ->where('id', $upgradeId) + ->update([ + 'target_snapshot' => json_encode( + $target, + JSON_THROW_ON_ERROR + ), + 'target_fingerprint' => $targetFingerprint, + 'updated_at' => now(), + ]); + $upgrade->refresh(); + $reservation = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->first(); + $this->assertNotNull($reservation); + $payload = json_decode( + (string) $reservation->configuration_payload, + true, + 512, + JSON_THROW_ON_ERROR + ); + $payload['target_fingerprint'] = $targetFingerprint; + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + 'configuration_fingerprint' => + (new UpgradeReservationIntegrityService) + ->fingerprint($upgrade, $payload), + 'updated_at' => now(), + ]); + + $blocker = collect( + (new LegacyReservationReadinessService)->blockers() + )->firstWhere('reservation_id', $reservationId); + + $this->assertNotNull($blocker); + $this->assertContains( + 'valid configuration_fingerprint', + $blocker['missing'] + ); + } + private function service(): Service { $user = User::factory()->create(); @@ -253,6 +963,724 @@ private function service(): Service ]); } + /** + * @return array{ + * reservation_id: int, + * service: Service, + * server: Server, + * panel: string, + * payload: array, + * invoice_id: int + * } + */ + private function insertCompleteCheckoutReservation( + string $status = 'confirmed', + bool $withAllocation = true, + ?Service $service = null, + ?Server $server = null + ): array { + if ($service === null || $server === null) { + $fixture = $this->dynamicServiceFixture( + match ($status) { + 'pending' => Service::STATUS_PENDING, + 'paid_committed' => Service::STATUS_PROVISIONING, + default => Service::STATUS_ACTIVE, + } + ); + $service = $fixture['service']; + $server = $fixture['server']; + $panel = $fixture['panel']; + } else { + $panel = hash('sha256', 'https://panel.example.com'); + } + + $service->load([ + 'user', + 'product.server', + 'configs.configOption', + ]); + $payload = $this->completeCheckoutPayload($service, $panel); + $invoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'currency_code' => 'USD', + 'status' => $status === 'pending' + ? Invoice::STATUS_PENDING + : Invoice::STATUS_PAID, + ]); + $invoice->items()->create([ + 'description' => 'Dynamic service', + 'price' => $payload['calculated_price'], + 'quantity' => 1, + 'reference_id' => $service->id, + 'reference_type' => Service::class, + ]); + $confirmed = $status === 'confirmed'; + $reservationId = $this->insertReservation($service, [ + 'purpose' => 'checkout', + 'status' => $status, + 'cart_id' => 99, + 'cart_item_guard_id' => 199, + 'service_guard_id' => $service->id, + 'server_extension_id' => $server->id, + 'panel_identity' => $panel, + 'configuration_fingerprint' => + (new ReservationConfigurationService) + ->fingerprint($payload), + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + 'calculated_price' => $payload['calculated_price'], + 'pricing_version' => $payload['pricing_version'], + 'formula_version' => $payload['formula_version'], + 'invoice_id' => $invoice->id, + 'expires_at' => $confirmed + ? now()->subDay() + : now()->addDay(), + 'guaranteed_until' => $confirmed + ? now()->subDay() + : now()->addDay(), + 'consumed_at' => $confirmed ? now()->subDay() : null, + 'external_server_id' => $confirmed ? 71 : null, + 'external_user_id' => $confirmed ? 44 : null, + 'external_server_uuid' => $confirmed + ? '2f4f28b0-0f36-4e6b-a2aa-a686c3466696' + : null, + 'external_server_identifier' => $confirmed + ? 'server-71' + : null, + ]); + if ($withAllocation) { + $this->insertAllocation( + $reservationId, + $panel, + released: $confirmed + ); + } + + return [ + 'reservation_id' => $reservationId, + 'service' => $service, + 'server' => $server, + 'panel' => $panel, + 'payload' => $payload, + 'invoice_id' => (int) $invoice->id, + ]; + } + + /** + * @return array{service: Service, server: Server, panel: string} + */ + private function dynamicServiceFixture( + string $status = Service::STATUS_ACTIVE + ): array { + $panel = hash('sha256', 'https://panel.example.com'); + $server = Server::create([ + 'name' => 'Pterodactyl', + 'extension' => 'Pterodactyl', + 'type' => 'server', + 'enabled' => true, + ]); + $server->settings()->create([ + 'key' => 'host', + 'value' => 'https://panel.example.com', + 'type' => 'string', + 'encrypted' => false, + ]); + $product = Product::factory()->create([ + 'server_id' => $server->id, + 'hidden' => false, + ]); + $plan = Plan::factory()->create([ + 'priceable_id' => $product->id, + 'priceable_type' => Product::class, + ]); + foreach ([ + 'location_ids' => [[3], 'array'], + 'nest_id' => [1, 'integer'], + 'egg_id' => [2, 'integer'], + ] as $key => [$value, $type]) { + $product->settings()->create([ + 'key' => $key, + 'value' => $value, + 'type' => $type, + 'encrypted' => false, + ]); + } + Price::factory()->create([ + 'plan_id' => $plan->id, + 'price' => 10, + 'setup_fee' => 0, + 'currency_code' => 'USD', + ]); + $resources = [ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + ]; + $options = []; + foreach ($resources as $resource => $value) { + $options[$resource] = $this->dynamicOption( + $product, + $resource + ); + } + $service = CapacityServiceCreationCoordinator::run( + function () use ( + $product, + $plan, + $options, + $resources, + $status + ): Service { + $service = Service::factory()->create([ + 'user_id' => User::factory()->create()->id, + 'product_id' => $product->id, + 'plan_id' => $plan->id, + 'status' => $status, + 'price' => 10, + 'quantity' => 1, + 'currency_code' => 'USD', + 'expires_at' => now()->addMonth(), + ]); + foreach ($resources as $resource => $value) { + $service->configs()->create([ + 'config_option_id' => $options[$resource]->id, + 'config_value_id' => null, + 'slider_value' => $value, + ]); + } + + return $service; + } + ); + + return compact('service', 'server', 'panel'); + } + + /** + * @return array + */ + private function completeCheckoutPayload( + Service $service, + string $panel, + mixed $memory = 4096, + int $quantity = 1 + ): array { + $service->loadMissing([ + 'product.server', + 'configs.configOption', + ]); + $configOptions = $service->configs + ->sortBy('config_option_id') + ->map(function ($config) use ($memory): array { + $option = $config->configOption; + $resource = strtolower((string) ( + $option?->getMetadata('resource_type', '') + )); + $value = $resource === 'memory' + ? $memory + : $config->slider_value; + + return [ + 'id' => (int) $config->config_option_id, + 'type' => (string) ($option?->type ?? ''), + 'environment_key' => strtolower((string) ( + $option?->env_variable ?: $option?->name + )), + 'resource_type' => $resource ?: null, + 'value' => is_numeric($value) + ? (float) $value + : $value, + 'metadata' => (array) ($option?->metadata ?? []), + ]; + }) + ->values() + ->all(); + $calculatedPrice = number_format( + (float) $service->price, + 2, + '.', + '' + ); + $payload = [ + 'customer_id' => $service->user_id, + 'cart_id' => 99, + 'server_extension_id' => + (int) ($service->product?->server_id ?? 41), + 'panel_identity' => $panel, + 'product_id' => $service->product_id, + 'plan_id' => $service->plan_id, + 'quantity' => $quantity, + 'currency_code' => 'USD', + 'resources' => [ + 'memory' => $memory, + 'cpu' => 200, + 'disk' => 20480, + ], + 'location_id' => 3, + 'node_id' => 7, + 'calculated_price' => $calculatedPrice, + 'formula_version' => 'dynamic-pterodactyl-v1', + 'config_options' => $configOptions, + 'allocation_requirements' => [ + 'required_count' => 1, + ], + 'provisioning_identity' => [ + 'nest_id' => 1, + 'egg_id' => 2, + 'user_external_id' => + "paymenter-user-{$service->user_id}", + 'user_email' => (string) $service->user->email, + ], + 'allocations' => [[ + 'allocation_id' => 7001, + 'ip' => '192.0.2.10', + 'port' => 25565, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ]], + ]; + $payload['pricing_version'] = + (new ReservationConfigurationService)->fingerprint([ + 'product_id' => (int) $service->product_id, + 'plan_id' => (int) $service->plan_id, + 'currency_code' => 'USD', + 'calculated_price' => $calculatedPrice, + 'config_options' => $configOptions, + ]); + + return $payload; + } + + private function insertReleasedAllocation( + int $reservationId, + string $panel + ): void { + $this->insertAllocation($reservationId, $panel, released: true); + } + + private function insertAllocation( + int $reservationId, + string $panel, + bool $released, + int $allocationId = 7001 + ): void { + DB::table('ptero_reservation_allocations')->insert([ + 'reservation_id' => $reservationId, + 'panel_identity' => $panel, + 'node_id' => 7, + 'allocation_id' => $allocationId, + 'ip' => '192.0.2.10', + 'port' => $allocationId === 7001 ? 25565 : 25566, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + 'released_at' => $released ? now() : null, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + + private function insertCompleteUpgradeReservation(): int + { + $panel = hash('sha256', 'https://panel.example.com'); + $server = Server::create([ + 'name' => 'Pterodactyl', + 'extension' => 'Pterodactyl', + 'type' => 'server', + 'enabled' => true, + ]); + $server->settings()->create([ + 'key' => 'host', + 'value' => 'https://panel.example.com', + 'type' => 'string', + 'encrypted' => false, + ]); + $product = Product::factory()->create([ + 'server_id' => $server->id, + 'hidden' => false, + ]); + $plan = Plan::factory()->create([ + 'priceable_id' => $product->id, + 'priceable_type' => Product::class, + ]); + foreach ([ + 'location_ids' => [[3], 'array'], + 'nest_id' => [1, 'integer'], + 'egg_id' => [2, 'integer'], + ] as $key => [$value, $type]) { + $product->settings()->create([ + 'key' => $key, + 'value' => $value, + 'type' => $type, + 'encrypted' => false, + ]); + } + Price::factory()->create([ + 'plan_id' => $plan->id, + 'price' => 10, + 'setup_fee' => 0, + 'currency_code' => 'USD', + ]); + $source = [ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + ]; + $target = [ + 'memory' => 8192, + 'cpu' => 400, + 'disk' => 40960, + ]; + $delta = [ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + ]; + $options = []; + foreach ($source as $resource => $value) { + $options[$resource] = $this->dynamicOption( + $product, + $resource + ); + } + $service = CapacityServiceCreationCoordinator::run(function () use ( + $product, + $plan, + $options, + $source + ): Service { + $service = Service::factory()->create([ + 'user_id' => User::factory()->create()->id, + 'product_id' => $product->id, + 'plan_id' => $plan->id, + 'status' => Service::STATUS_ACTIVE, + 'price' => 10, + 'quantity' => 1, + 'currency_code' => 'USD', + 'expires_at' => now()->addMonth(), + ]); + foreach ($source as $resource => $value) { + $service->configs()->create([ + 'config_option_id' => $options[$resource]->id, + 'config_value_id' => null, + 'slider_value' => $value, + ]); + } + + return $service; + }); + + $this->insertCompleteCheckoutReservation( + service: $service, + server: $server + ); + + $invoice = \App\Models\Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'currency_code' => 'USD', + 'status' => \App\Models\Invoice::STATUS_PENDING, + ]); + $upgrade = ServiceUpgrade::create([ + 'service_id' => $service->id, + 'product_id' => $service->product_id, + 'plan_id' => $service->plan_id, + 'invoice_id' => $invoice->id, + 'status' => 'awaiting_payment', + 'active_service_guard_id' => $service->id, + 'type' => 'config_options', + 'quoted_amount' => '100.00', + 'currency_code' => 'USD', + 'credit_amount' => 0, + 'provisioning_attempts' => 0, + ]); + foreach ($target as $resource => $value) { + $upgrade->configs()->create([ + 'config_option_id' => $options[$resource]->id, + 'config_value_id' => null, + 'slider_value' => $value, + ]); + } + $upgrade->load([ + 'service.product.server.settings', + 'service.product.settings', + 'service.plan.prices', + 'service.configs.configOption', + 'service.configs.configValue', + 'product.server.settings', + 'product.settings', + 'plan.prices', + 'configs.configOption', + 'configs.configValue', + ]); + $upgrade->captureSnapshots(); + $upgrade->save(); + $invoice->items()->create([ + 'description' => 'Resource upgrade', + 'price' => '100.00', + 'quantity' => 1, + 'reference_id' => $upgrade->id, + 'reference_type' => ServiceUpgrade::class, + ]); + $sourceFingerprint = (string) $upgrade->source_fingerprint; + $targetFingerprint = (string) $upgrade->target_fingerprint; + $upgradeId = (int) $upgrade->id; + $payload = [ + 'service_upgrade_id' => $upgradeId, + 'source_fingerprint' => $sourceFingerprint, + 'target_fingerprint' => $targetFingerprint, + 'panel_identity' => $panel, + 'node_id' => 7, + 'location_id' => 3, + 'external_server_id' => 71, + 'external_server_uuid' => + '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', + 'external_server_identifier' => 'server-71', + 'external_server_external_id' => (string) $service->id, + 'external_user_id' => 44, + 'user_external_id' => + "paymenter-user-{$service->user_id}", + 'user_email' => (string) $service->user->email, + 'nest_id' => 1, + 'egg_id' => 2, + 'preserved_build' => [ + 'swap' => 0, + 'io' => 500, + 'threads' => null, + 'databases' => 0, + 'allocations' => 0, + 'backups' => 0, + ], + 'allocation_id' => 7001, + 'assigned_allocation_ids' => [7001], + 'source' => $source, + 'target' => $target, + 'delta' => $delta, + ]; + + return $this->insertReservation($service, [ + 'purpose' => 'upgrade', + 'status' => 'pending', + 'service_guard_id' => null, + 'server_extension_id' => $server->id, + 'service_upgrade_id' => $upgradeId, + 'upgrade_guard_id' => $upgradeId, + 'panel_identity' => $panel, + 'configuration_fingerprint' => + (new UpgradeReservationIntegrityService) + ->fingerprint($upgrade, $payload), + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + 'node_id' => 7, + 'location_id' => 3, + 'memory' => $target['memory'], + 'cpu' => $target['cpu'], + 'disk' => $target['disk'], + 'reserved_memory' => $delta['memory'], + 'reserved_cpu' => $delta['cpu'], + 'reserved_disk' => $delta['disk'], + 'external_server_id' => 71, + 'external_user_id' => 44, + 'external_server_uuid' => + '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', + 'external_server_identifier' => 'server-71', + 'calculated_price' => '100.00', + 'pricing_version' => + (new UpgradeReservationIntegrityService) + ->pricingVersion($upgrade), + 'formula_version' => 'dynamic-upgrade-v1', + 'invoice_id' => $invoice->id, + 'expires_at' => now()->addDay(), + 'guaranteed_until' => now()->addDay(), + 'consumed_at' => null, + ]); + } + + private function upgradeIdForReservation(int $reservationId): int + { + $upgradeId = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('service_upgrade_id'); + $this->assertNotNull($upgradeId); + + return (int) $upgradeId; + } + + private function completeUpgrade( + int $reservationId, + bool $applyTarget + ): void { + $reservation = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->first(); + $this->assertNotNull($reservation); + $upgrade = ServiceUpgrade::query() + ->findOrFail((int) $reservation->service_upgrade_id); + $target = (array) $upgrade->target_snapshot; + $targetProperties = (array) ($target['properties'] ?? []); + + if ($applyTarget) { + foreach (['memory', 'cpu', 'disk'] as $resource) { + $optionId = DB::table('config_options') + ->where('env_variable', $resource) + ->whereExists( + function ($query) use ($upgrade): void { + $query->selectRaw('1') + ->from('config_option_products') + ->whereColumn( + 'config_option_products.config_option_id', + 'config_options.id' + ) + ->where( + 'config_option_products.product_id', + $upgrade->product_id + ); + } + ) + ->value('id'); + $this->assertNotNull($optionId); + DB::table('service_configs') + ->where('configurable_type', Service::class) + ->where('configurable_id', $upgrade->service_id) + ->where('config_option_id', $optionId) + ->update([ + 'slider_value' => $targetProperties[$resource], + 'updated_at' => now(), + ]); + } + DB::table('services') + ->where('id', $upgrade->service_id) + ->update([ + 'price' => $target['recurring_price'], + 'updated_at' => now(), + ]); + } + + DB::table('invoices') + ->where('id', $upgrade->invoice_id) + ->update([ + 'status' => Invoice::STATUS_PAID, + 'updated_at' => now(), + ]); + DB::table('service_upgrades') + ->where('id', $upgrade->id) + ->update([ + 'status' => ServiceUpgrade::STATUS_COMPLETED, + 'active_service_guard_id' => null, + 'completed_at' => now(), + 'updated_at' => now(), + ]); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'status' => 'confirmed', + 'upgrade_guard_id' => null, + 'consumed_at' => now(), + 'updated_at' => now(), + ]); + } + + /** + * @param array $overrides + */ + private function duplicateReservation( + int $reservationId, + array $overrides = [] + ): int { + $row = (array) DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->first(); + $this->assertNotSame([], $row); + foreach ([ + 'id', + 'active_idempotency_key', + 'active_cart_item_id', + 'active_upgrade_id', + 'active_checkout_service_id', + ] as $generatedColumn) { + unset($row[$generatedColumn]); + } + $row['token'] = bin2hex(random_bytes(32)); + $row['created_at'] = now(); + $row['updated_at'] = now(); + + return DB::table('ptero_resource_reservations')->insertGetId( + array_merge($row, $overrides) + ); + } + + private function invokeCheckoutCommitmentPreflight(): void + { + $migration = require dirname(__DIR__, 2) + .'/database/migrations/' + .'2026_07_26_000030_enforce_one_checkout_commitment_per_service.php'; + $method = new \ReflectionMethod( + $migration, + 'assertNoDuplicateCheckoutCommitments' + ); + $method->setAccessible(true); + $method->invoke($migration); + } + + /** + * @param array $snapshot + */ + private function upgradeSnapshotFingerprint(array $snapshot): string + { + $canonicalize = function (array $value) use (&$canonicalize): array { + foreach ($value as $key => $item) { + if (is_array($item)) { + $value[$key] = $canonicalize($item); + } + } + if (! array_is_list($value)) { + ksort($value); + } + + return $value; + }; + + return hash('sha256', json_encode( + $canonicalize($snapshot), + JSON_THROW_ON_ERROR + | JSON_PRESERVE_ZERO_FRACTION + | JSON_UNESCAPED_SLASHES + )); + } + + private function dynamicOption( + Product $product, + string $resource + ): ConfigOption { + $option = ConfigOption::create([ + 'name' => ucfirst($resource), + 'env_variable' => $resource, + 'type' => 'dynamic_slider', + 'hidden' => false, + 'upgradable' => true, + 'metadata' => [ + 'resource_type' => $resource, + 'min' => 1, + 'max' => 100000, + 'step' => 1, + 'default' => 1, + 'display_divisor' => 1, + 'pricing' => [ + 'model' => 'linear', + 'rate_per_unit' => 1, + ], + ], + ]); + ConfigOptionProduct::create([ + 'product_id' => $product->id, + 'config_option_id' => $option->id, + ]); + + return $option; + } + /** * @param array $overrides */ diff --git a/tests/Feature/ResourceQuoteApiTest.php b/tests/Feature/ResourceQuoteApiTest.php index 4e4b045..e983817 100644 --- a/tests/Feature/ResourceQuoteApiTest.php +++ b/tests/Feature/ResourceQuoteApiTest.php @@ -10,6 +10,8 @@ use Illuminate\Support\Facades\DB; use Mockery; use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\StockUnavailableException; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\QuoteRateLimitConfigurationService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\QuoteRateLimiterService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceQuoteService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; @@ -21,6 +23,11 @@ protected function setUp(): void { parent::setUp(); + (new QuoteRateLimiterService( + new QuoteRateLimitConfigurationService([ + 'pterodactyl_url' => 'https://panel.example.com', + ]) + ))->register(); require __DIR__.'/../../routes/api.php'; } @@ -132,6 +139,72 @@ public function test_upstream_failure_does_not_leak_panel_details(): void $this->assertStringNotContainsString('panel-internal', $response->getContent()); } + public function test_customer_quote_route_enforces_the_per_ip_budget(): void + { + $this->registerQuoteLimiter( + perIp: 1, + global: 10, + panelUrl: 'https://per-ip-rate-limit.example.com' + ); + $product = $this->quoteableProduct(); + $quotes = Mockery::mock(ResourceQuoteService::class); + $quotes->shouldReceive('quote') + ->once() + ->andReturn([ + 'available' => true, + 'adjusted' => false, + 'selection' => [ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 51200, + ], + 'bounds' => [], + ]); + $this->app->instance(ResourceQuoteService::class, $quotes); + $endpoint = + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote"; + + $this->withServerVariables(['REMOTE_ADDR' => '192.0.2.10']) + ->postJson($endpoint, ['config_options' => []]) + ->assertOk(); + $this->withServerVariables(['REMOTE_ADDR' => '192.0.2.10']) + ->postJson($endpoint, ['config_options' => []]) + ->assertStatus(429); + } + + public function test_customer_quote_route_enforces_the_panel_global_budget(): void + { + $this->registerQuoteLimiter( + perIp: 10, + global: 1, + panelUrl: 'https://global-rate-limit.example.com' + ); + $product = $this->quoteableProduct(); + $quotes = Mockery::mock(ResourceQuoteService::class); + $quotes->shouldReceive('quote') + ->once() + ->andReturn([ + 'available' => true, + 'adjusted' => false, + 'selection' => [ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 51200, + ], + 'bounds' => [], + ]); + $this->app->instance(ResourceQuoteService::class, $quotes); + $endpoint = + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote"; + + $this->withServerVariables(['REMOTE_ADDR' => '192.0.2.20']) + ->postJson($endpoint, ['config_options' => []]) + ->assertOk(); + $this->withServerVariables(['REMOTE_ADDR' => '192.0.2.21']) + ->postJson($endpoint, ['config_options' => []]) + ->assertStatus(429); + } + public function test_owned_cart_item_quote_excludes_its_current_hold(): void { $product = $this->quoteableProduct(); @@ -188,6 +261,62 @@ public function test_owned_cart_item_quote_excludes_its_current_hold(): void ->assertOk(); } + public function test_owned_expired_cart_hold_is_excluded_until_cart_mutation_retires_it(): void + { + $product = $this->quoteableProduct(); + $cart = Cart::create(['currency_code' => 'USD']); + $cartItemId = DB::table('cart_items')->insertGetId([ + 'cart_id' => $cart->id, + 'product_id' => $product->id, + 'plan_id' => $product->plans()->value('id'), + 'config_options' => json_encode([]), + 'checkout_config' => json_encode([]), + 'quantity' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); + DB::table('ptero_resource_reservations')->insert([ + 'token' => 'owned-expired-cart-hold', + 'cart_item_id' => $cartItemId, + 'cart_item_guard_id' => $cartItemId, + 'node_id' => 5, + 'location_id' => 1, + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 51200, + 'calculated_price' => 0, + 'pricing_breakdown' => json_encode([]), + 'status' => 'pending', + 'expires_at' => now()->subMinute(), + 'created_at' => now()->subMinutes(16), + 'updated_at' => now()->subMinutes(16), + ]); + + $quotes = Mockery::mock(ResourceQuoteService::class); + $quotes->shouldReceive('quote') + ->once() + ->with( + Mockery::on(fn (Product $resolved): bool => $resolved->is($product)), + [], + 'owned-expired-cart-hold' + ) + ->andReturn([ + 'available' => true, + 'adjusted' => false, + 'selection' => ['memory' => 4096, 'cpu' => 200, 'disk' => 51200], + 'bounds' => [], + ]); + $this->app->instance(ResourceQuoteService::class, $quotes); + + $this->withCredentials() + ->withCookie('cart', $cart->ulid) + ->postJson( + "/api/dynamic-pterodactyl/products/{$product->id}/resource-quote", + ['config_options' => [], 'cart_item_id' => $cartItemId] + ) + ->assertOk(); + } + public function test_cart_item_from_another_cart_cannot_be_used_for_exclusion(): void { $product = $this->quoteableProduct(); @@ -314,4 +443,18 @@ private function quoteableProduct(): Product return $product; } + + private function registerQuoteLimiter( + int $perIp = 10, + int $global = 60, + string $panelUrl = 'https://panel.example.com' + ): void { + (new QuoteRateLimiterService( + new QuoteRateLimitConfigurationService([ + 'pterodactyl_url' => $panelUrl, + 'quote_rate_limit_per_ip' => $perIp, + 'quote_rate_limit_global' => $global, + ]) + ))->register(); + } } diff --git a/tests/Unit/ConfigOptionSetupServiceTest.php b/tests/Unit/ConfigOptionSetupServiceTest.php index 16da5a8..d1d79d9 100644 --- a/tests/Unit/ConfigOptionSetupServiceTest.php +++ b/tests/Unit/ConfigOptionSetupServiceTest.php @@ -173,6 +173,28 @@ public function test_fractional_display_value_that_cannot_scale_exactly_is_rejec ); } + public function test_zero_resource_minimum_is_rejected_before_it_can_mean_unlimited(): void + { + $product = $this->eligibleProduct(); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Memory minimum must be greater than zero.' + ); + + app(ConfigOptionSetupService::class)->createDynamicSliderOptions( + $product->id, + [ + 'pricing_model' => 'linear', + 'memory_min' => 0, + 'memory_rate' => 1, + 'cpu_rate' => 1, + 'disk_rate' => 1, + ], + [['id' => 1, 'short' => 'nyc', 'long' => 'New York']] + ); + } + public function test_scaled_value_overflow_is_rejected(): void { $product = $this->eligibleProduct(); diff --git a/tests/Unit/PterodactylInventoryServiceTest.php b/tests/Unit/PterodactylInventoryServiceTest.php index 3ccaced..83ea470 100644 --- a/tests/Unit/PterodactylInventoryServiceTest.php +++ b/tests/Unit/PterodactylInventoryServiceTest.php @@ -53,17 +53,18 @@ public function test_nodes_are_paginated_and_location_is_filtered_locally(): voi parse_str(parse_url($request->url(), PHP_URL_QUERY) ?? '', $query); $this->assertArrayNotHasKey('filter', $query); $this->assertSame('allocations', $query['include'] ?? null); + $this->assertSame('100', $query['per_page'] ?? null); $page = (int) ($query['page'] ?? 1); - - return Http::response([ - 'data' => $page === 1 - ? [$this->nodeResource(10, 1), $this->nodeResource(20, 2)] - : [$this->nodeResource(30, 1)], - 'meta' => ['pagination' => [ - 'current_page' => $page, - 'total_pages' => 2, - ]], - ]); + $data = $page === 1 + ? [$this->nodeResource(10, 1), $this->nodeResource(20, 2)] + : [$this->nodeResource(30, 1)]; + + return Http::response($this->paginatedPayload( + $data, + currentPage: $page, + total: 3, + perPage: 2 + )); }); $nodes = $this->inventory->nodesInLocation(1); @@ -90,17 +91,242 @@ public function test_nodes_are_paginated_and_location_is_filtered_locally(): voi Http::assertSentCount(2); } + public function test_last_page_alias_is_accepted_as_a_complete_termination_proof(): void + { + $payload = $this->paginatedPayload([ + $this->locationResource(1), + ]); + $payload['meta']['pagination']['last_page'] = + $payload['meta']['pagination']['total_pages']; + unset( + $payload['meta']['pagination']['count'], + $payload['meta']['pagination']['total_pages'] + ); + + Http::fake([ + '*' => Http::response($payload), + ]); + + $this->assertSame([1], array_column( + $this->inventory->locations(), + 'id' + )); + } + + public function test_missing_pagination_metadata_fails_inventory_closed(): void + { + Http::fake([ + '*' => Http::response([ + 'data' => [$this->locationResource(1)], + ]), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('invalid pagination metadata'); + + $this->inventory->locations(); + } + + public function test_incomplete_pagination_metadata_fails_inventory_closed(): void + { + $payload = $this->paginatedPayload([ + $this->locationResource(1), + ]); + unset($payload['meta']['pagination']['total']); + + Http::fake([ + '*' => Http::response($payload), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('pagination.total'); + + $this->inventory->locations(); + } + + public function test_pagination_rejects_a_skipped_first_page(): void + { + Http::fake([ + '*' => Http::response($this->paginatedPayload( + [$this->locationResource(1)], + currentPage: 2, + total: 2, + perPage: 1 + )), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('skipped, repeated, or returned an unexpected page'); + + $this->inventory->locations(); + } + + public function test_pagination_rejects_a_repeated_page(): void + { + Http::fakeSequence() + ->push($this->paginatedPayload( + [$this->locationResource(1)], + currentPage: 1, + total: 2, + perPage: 1 + )) + ->push($this->paginatedPayload( + [$this->locationResource(2)], + currentPage: 1, + total: 2, + perPage: 1 + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('skipped, repeated, or returned an unexpected page'); + + $this->inventory->locations(); + } + + public function test_pagination_rejects_changed_totals_between_pages(): void + { + Http::fakeSequence() + ->push($this->paginatedPayload( + [$this->locationResource(1)], + currentPage: 1, + total: 2, + perPage: 1 + )) + ->push($this->paginatedPayload( + [$this->locationResource(2)], + currentPage: 2, + total: 3, + perPage: 1 + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('metadata changed during the inventory read'); + + $this->inventory->locations(); + } + + public function test_pagination_rejects_duplicate_resources_across_pages(): void + { + Http::fakeSequence() + ->push($this->paginatedPayload( + [$this->locationResource(1)], + currentPage: 1, + total: 2, + perPage: 1 + )) + ->push($this->paginatedPayload( + [$this->locationResource(1)], + currentPage: 2, + total: 2, + perPage: 1 + )); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('duplicate resource'); + + $this->inventory->locations(); + } + + public function test_pagination_rejects_a_short_non_final_page(): void + { + Http::fake([ + '*' => Http::response($this->paginatedPayload( + [$this->locationResource(1)], + currentPage: 1, + total: 3, + perPage: 2 + )), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('page size is inconsistent'); + + $this->inventory->locations(); + } + + public function test_pagination_rejects_an_incorrect_advertised_count(): void + { + $payload = $this->paginatedPayload([ + $this->locationResource(1), + ]); + $payload['meta']['pagination']['count'] = 0; + + Http::fake([ + '*' => Http::response($payload), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('count does not match'); + + $this->inventory->locations(); + } + + public function test_pagination_rejects_conflicting_final_page_fields(): void + { + $payload = $this->paginatedPayload([ + $this->locationResource(1), + ]); + $payload['meta']['pagination']['last_page'] = 2; + + Http::fake([ + '*' => Http::response($payload), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('conflicting final pages'); + + $this->inventory->locations(); + } + + public function test_pagination_rejects_a_final_page_inconsistent_with_total(): void + { + $payload = $this->paginatedPayload([ + $this->locationResource(1), + ]); + $payload['meta']['pagination']['total_pages'] = 2; + + Http::fake([ + '*' => Http::response($payload), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('total is inconsistent'); + + $this->inventory->locations(); + } + + public function test_pagination_enforces_a_safe_page_limit_before_following_pages(): void + { + Http::fake([ + '*' => Http::response($this->paginatedPayload( + [$this->locationResource(1)], + currentPage: 1, + total: 1001, + perPage: 1 + )), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('safe page limit'); + + try { + $this->inventory->locations(); + } finally { + Http::assertSentCount(1); + } + } + public function test_locations_use_stock_application_api_shape(): void { Http::fake([ - '*' => Http::response(['data' => [[ + '*' => Http::response($this->paginatedPayload([[ 'object' => 'location', 'attributes' => [ 'id' => 1, 'short' => 'mel', 'long' => 'Melbourne', ], - ]]]), + ]])), ]); $this->assertSame([[ @@ -113,11 +339,11 @@ public function test_locations_use_stock_application_api_shape(): void public function test_free_allocation_reports_when_its_ip_is_already_assigned(): void { $node = $this->nodeResource(10, 1); - $node['relationships']['allocations']['data'][] = + $node['attributes']['relationships']['allocations']['data'][] = $this->allocationResource(10002, true); Http::fake([ - '*' => Http::response(['data' => [$node]]), + '*' => Http::response($this->paginatedPayload([$node])), ]); $allocations = $this->inventory->nodes()[0]['available_allocations']; @@ -158,31 +384,32 @@ public function test_server_and_allocation_shapes_are_read_without_optimistic_de if (str_contains($request->url(), '/api/application/servers')) { $this->assertSame('allocations', $query['include'] ?? null); - - return Http::response([ - 'data' => $page === 1 - ? [$this->serverResource(44, 10, 4096, 200, 20480, 501)] - : [$this->serverResource(45, 10, 2048, 100, 10240, 502)], - 'meta' => ['pagination' => [ - 'current_page' => $page, - 'total_pages' => 2, - ]], - ]); + $data = $page === 1 + ? [$this->serverResource(44, 10, 4096, 200, 20480, 501)] + : [$this->serverResource(45, 10, 2048, 100, 10240, 502)]; + + return Http::response($this->paginatedPayload( + $data, + currentPage: $page, + total: 2, + perPage: 1 + )); } if (str_contains($request->url(), '/nodes/10/allocations')) { - return Http::response([ - 'data' => $page === 1 - ? [ - $this->allocationResource(501, true), - $this->allocationResource(502, false), - ] - : [$this->allocationResource(503, false)], - 'meta' => ['pagination' => [ - 'current_page' => $page, - 'total_pages' => 2, - ]], - ]); + $data = $page === 1 + ? [ + $this->allocationResource(501, true), + $this->allocationResource(502, false), + ] + : [$this->allocationResource(503, false)]; + + return Http::response($this->paginatedPayload( + $data, + currentPage: $page, + total: 3, + perPage: 2 + )); } return Http::response([], 404); @@ -221,7 +448,7 @@ public function test_missing_overallocation_field_fails_inventory_closed(): void unset($node['attributes']['memory_overallocate']); Http::fake([ - '*' => Http::response(['data' => [$node]]), + '*' => Http::response($this->paginatedPayload([$node])), ]); $this->expectException(\RuntimeException::class); @@ -236,7 +463,7 @@ public function test_integer_overflow_is_rejected_instead_of_saturated(): void $node['attributes']['memory'] = '999999999999999999999999999999'; Http::fake([ - '*' => Http::response(['data' => [$node]]), + '*' => Http::response($this->paginatedPayload([$node])), ]); $this->expectException(\RuntimeException::class); @@ -251,7 +478,7 @@ public function test_customer_allocation_headroom_is_derived_from_assigned_relat $server['attributes']['feature_limits']['allocations'] = 2; Http::fake([ - '*' => Http::response(['data' => [$server]]), + '*' => Http::response($this->paginatedPayload([$server])), ]); $inventory = $this->inventory->serversForNodes([10])[10][0]; @@ -264,10 +491,89 @@ public function test_customer_allocation_headroom_is_derived_from_assigned_relat public function test_missing_server_allocation_relationship_fails_inventory_closed(): void { $server = $this->serverResource(44, 10, 4096, 200, 20480, 501); - unset($server['relationships']); + unset($server['attributes']['relationships']); + + Http::fake([ + '*' => Http::response($this->paginatedPayload([$server])), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('allocations relationship'); + + $this->inventory->serversForNodes([10]); + } + + public function test_official_nested_relationships_override_legacy_root_values(): void + { + $node = $this->nodeResource(10, 1); + $node['relationships']['allocations']['data'] = []; + $server = $this->serverResource(44, 10, 4096, 200, 20480, 501); + $server['relationships']['allocations']['data'] = []; + + Http::fake(function ($request) use ($node, $server) { + if (str_contains($request->url(), '/api/application/nodes')) { + return Http::response($this->paginatedPayload([$node])); + } + + return Http::response($this->paginatedPayload([$server])); + }); + + $this->assertSame( + [10001], + array_column( + $this->inventory->nodes()[0]['available_allocations'], + 'id' + ) + ); + $this->assertSame( + [501], + $this->inventory->serversForNodes([10])[10][0][ + 'assigned_allocation_ids' + ] + ); + } + + public function test_legacy_root_relationships_remain_an_explicit_fallback(): void + { + $node = $this->nodeResource(10, 1); + $node['relationships'] = $node['attributes']['relationships']; + unset($node['attributes']['relationships']); + $server = $this->serverResource(44, 10, 4096, 200, 20480, 501); + $server['relationships'] = $server['attributes']['relationships']; + unset($server['attributes']['relationships']); + + Http::fake(function ($request) use ($node, $server) { + if (str_contains($request->url(), '/api/application/nodes')) { + return Http::response($this->paginatedPayload([$node])); + } + + return Http::response($this->paginatedPayload([$server])); + }); + + $this->assertSame( + [10001], + array_column( + $this->inventory->nodes()[0]['available_allocations'], + 'id' + ) + ); + $this->assertSame( + [501], + $this->inventory->serversForNodes([10])[10][0][ + 'assigned_allocation_ids' + ] + ); + } + + public function test_malformed_official_relationship_is_not_masked_by_root_fallback(): void + { + $server = $this->serverResource(44, 10, 4096, 200, 20480, 501); + $server['relationships'] = $server['attributes']['relationships']; + $server['attributes']['relationships']['allocations']['data'] = + 'not-a-list'; Http::fake([ - '*' => Http::response(['data' => [$server]]), + '*' => Http::response($this->paginatedPayload([$server])), ]); $this->expectException(\RuntimeException::class); @@ -282,7 +588,7 @@ public function test_missing_server_identity_fails_snapshot_proof_closed(): void unset($server['attributes']['uuid']); Http::fake([ - '*' => Http::response(['data' => [$server]]), + '*' => Http::response($this->paginatedPayload([$server])), ]); $this->expectException(\RuntimeException::class); @@ -307,13 +613,17 @@ public function test_connection_check_exercises_nodes_servers_and_allocations_pe ); $nodeIncludes[] = $query['include'] ?? null; - return Http::response(['data' => [$this->nodeResource(10, 1)]]); + return Http::response($this->paginatedPayload([ + $this->nodeResource(10, 1), + ])); } if (str_ends_with(parse_url($request->url(), PHP_URL_PATH), '/servers')) { - return Http::response(['data' => []]); + return Http::response($this->paginatedPayload([])); } if (str_contains($request->url(), '/nodes/10/allocations')) { - return Http::response(['data' => [$this->allocationResource(502, false)]]); + return Http::response($this->paginatedPayload([ + $this->allocationResource(502, false), + ])); } return Http::response([], 404); @@ -346,6 +656,49 @@ public function test_legacy_allocation_only_acknowledgement_is_not_a_capacity_gu $inventory->assertExclusiveProvisioningControl(); } + /** + * @param list> $data + * @return array + */ + private function paginatedPayload( + array $data, + int $currentPage = 1, + ?int $total = null, + int $perPage = 100 + ): array { + $total ??= count($data); + $totalPages = max( + 1, + intdiv($total, $perPage) + ($total % $perPage === 0 ? 0 : 1) + ); + + return [ + 'data' => $data, + 'meta' => [ + 'pagination' => [ + 'total' => $total, + 'count' => count($data), + 'per_page' => $perPage, + 'current_page' => $currentPage, + 'total_pages' => $totalPages, + 'links' => [], + ], + ], + ]; + } + + private function locationResource(int $id): array + { + return [ + 'object' => 'location', + 'attributes' => [ + 'id' => $id, + 'short' => 'loc-'.$id, + 'long' => 'Location '.$id, + ], + ]; + } + private function nodeResource(int $id, int $locationId): array { return [ @@ -366,14 +719,14 @@ private function nodeResource(int $id, int $locationId): array 'memory' => 1024, 'disk' => 2048, ], - ], - 'relationships' => [ - 'allocations' => [ - 'data' => [ - $this->allocationResource( - ($id * 1000) + 1, - false - ), + 'relationships' => [ + 'allocations' => [ + 'data' => [ + $this->allocationResource( + ($id * 1000) + 1, + false + ), + ], ], ], ], @@ -416,15 +769,15 @@ private function serverResource( 'io' => 500, 'threads' => null, ], - ], - 'relationships' => [ - 'allocations' => [ - 'data' => [[ - 'object' => 'allocation', - 'attributes' => [ - 'id' => $allocation, - ], - ]], + 'relationships' => [ + 'allocations' => [ + 'data' => [[ + 'object' => 'allocation', + 'attributes' => [ + 'id' => $allocation, + ], + ]], + ], ], ], ]; diff --git a/tests/Unit/QuoteRateLimiterServiceTest.php b/tests/Unit/QuoteRateLimiterServiceTest.php new file mode 100644 index 0000000..ac42d8d --- /dev/null +++ b/tests/Unit/QuoteRateLimiterServiceTest.php @@ -0,0 +1,147 @@ + 'HTTPS://Panel.Example.com:443/PanelA/', + 'pterodactyl_api_key' => 'must-not-be-in-a-rate-limit-key', + ]); + (new QuoteRateLimiterService($configuration))->register(); + + $limiter = RateLimiter::limiter(QuoteRateLimiterService::NAME); + $this->assertIsCallable($limiter); + $limits = $limiter(Request::create( + '/api/dynamic-pterodactyl/products/1/resource-quote', + 'POST', + server: ['REMOTE_ADDR' => '192.0.2.44'] + )); + $identity = PanelEndpointIdentity::hash( + 'https://panel.example.com/PanelA' + ); + + $this->assertCount(2, $limits); + $this->assertSame( + QuoteRateLimitConfigurationService::DEFAULT_PER_IP, + $limits[0]->maxAttempts + ); + $this->assertSame( + QuoteRateLimitConfigurationService::DEFAULT_GLOBAL, + $limits[1]->maxAttempts + ); + $this->assertSame(60, $limits[0]->decaySeconds); + $this->assertSame(60, $limits[1]->decaySeconds); + $this->assertSame( + "dynamic-pterodactyl:quotes:ip:{$identity}:192.0.2.44", + $limits[0]->key + ); + $this->assertSame( + "dynamic-pterodactyl:quotes:panel:{$identity}", + $limits[1]->key + ); + $this->assertStringNotContainsString( + 'must-not-be-in-a-rate-limit-key', + $limits[0]->key.$limits[1]->key + ); + } + + public function test_configured_budgets_are_bounded_and_applied(): void + { + $configuration = new QuoteRateLimitConfigurationService([ + 'pterodactyl_url' => 'https://panel.example.com', + 'quote_rate_limit_per_ip' => '7', + 'quote_rate_limit_global' => 42, + ]); + (new QuoteRateLimiterService($configuration))->register(); + + $limits = RateLimiter::limiter(QuoteRateLimiterService::NAME)( + Request::create('/', 'POST') + ); + + $this->assertSame(7, $limits[0]->maxAttempts); + $this->assertSame(42, $limits[1]->maxAttempts); + } + + #[DataProvider('invalidConfiguration')] + public function test_invalid_persisted_configuration_fails_closed( + array $configuration, + string $message + ): void { + $service = new QuoteRateLimitConfigurationService([ + 'pterodactyl_url' => 'https://panel.example.com', + ...$configuration, + ]); + + $this->expectException(InvalidStockConfigurationException::class); + $this->expectExceptionMessage($message); + + $service->configuration(); + } + + public static function invalidConfiguration(): array + { + return [ + 'zero per IP' => [[ + 'quote_rate_limit_per_ip' => 0, + ], 'per-IP quote rate limit must be between'], + 'excessive per IP' => [[ + 'quote_rate_limit_per_ip' => 61, + ], 'per-IP quote rate limit must be between'], + 'fractional global' => [[ + 'quote_rate_limit_global' => '1.5', + ], 'global quote rate limit must be a whole number'], + 'excessive global' => [[ + 'quote_rate_limit_global' => 241, + ], 'global quote rate limit must be between'], + ]; + } + + public function test_invalid_panel_url_fails_closed_before_a_key_is_built(): void + { + $service = new QuoteRateLimitConfigurationService([ + 'pterodactyl_url' => 'not a panel URL', + ]); + + $this->expectException(InvalidStockConfigurationException::class); + $this->expectExceptionMessage('valid Pterodactyl panel URL'); + + $service->configuration(); + } + + public function test_named_limiter_is_wired_only_to_customer_quote_routes(): void + { + require __DIR__.'/../../routes/api.php'; + + $checkout = Route::getRoutes()->match(Request::create( + '/api/dynamic-pterodactyl/products/1/resource-quote', + 'POST' + )); + $upgrade = Route::getRoutes()->match(Request::create( + '/api/dynamic-pterodactyl/services/1/upgrade-quote', + 'POST' + )); + $admin = Route::getRoutes()->match(Request::create( + '/api/dynamic-pterodactyl/admin/capacity', + 'GET' + )); + $middleware = 'throttle:'.QuoteRateLimiterService::NAME; + + $this->assertContains($middleware, $checkout->gatherMiddleware()); + $this->assertContains($middleware, $upgrade->gatherMiddleware()); + $this->assertNotContains($middleware, $admin->gatherMiddleware()); + $this->assertContains('throttle:30,1', $admin->gatherMiddleware()); + } +} diff --git a/tests/Unit/ReservationServiceTest.php b/tests/Unit/ReservationServiceTest.php index 1f06a0c..0e55022 100644 --- a/tests/Unit/ReservationServiceTest.php +++ b/tests/Unit/ReservationServiceTest.php @@ -5,6 +5,8 @@ use App\Jobs\Server\CreateJob; use App\Jobs\Server\SuspendJob; use App\Helpers\ExtensionHelper; +use App\Models\Cart; +use App\Models\CartItem; use App\Models\ConfigOption; use App\Models\Extension; use App\Models\Invoice; @@ -31,6 +33,7 @@ use Paymenter\Extensions\Others\DynamicPterodactyl\Models\ResourceReservation; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AuditLogService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\NodeSelectionService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ProductResourceConfigurationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationConfigurationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; @@ -65,7 +68,46 @@ protected function tearDown(): void public function test_guest_holds_transfer_with_cart_ownership(): void { $user = User::withoutEvents(fn () => User::factory()->create()); - $this->insertReservation(cartId: 71, userId: null); + $reservationId = $this->insertReservation( + cartId: 71, + userId: null + ); + $payload = json_decode( + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('configuration_payload'), + true, + 512, + JSON_THROW_ON_ERROR + ); + $payload['config_options'] = [[ + 'id' => 1, + 'value' => 4096.0, + ]]; + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'configuration_fingerprint' => + $this->configurationService->fingerprint($payload), + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + ]); + $persisted = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->first(); + $persistedPayload = json_decode( + $persisted->configuration_payload, + true, + 512, + JSON_THROW_ON_ERROR + ); + $this->assertSame( + $this->configurationService->fingerprint($persistedPayload), + $persisted->configuration_fingerprint, + 'The immutable fingerprint must survive a JSON-column numeric round trip before ownership transfer.' + ); $updated = $this->service()->transferCartOwnership(71, $user->id); @@ -77,6 +119,7 @@ public function test_guest_holds_transfer_with_cart_ownership(): void ]); $reservation = DB::table('ptero_resource_reservations')->where('cart_id', 71)->first(); $payload = json_decode($reservation->configuration_payload, true, 512, JSON_THROW_ON_ERROR); + $this->assertIsInt($payload['config_options'][0]['value']); $this->assertSame($user->id, $payload['customer_id']); $this->assertSame( $this->configurationService->fingerprint($payload), @@ -84,6 +127,71 @@ public function test_guest_holds_transfer_with_cart_ownership(): void ); } + public function test_cart_reservation_rejects_resource_slider_added_after_checkout_render(): void + { + $product = $this->pterodactylProduct(); + $memory = $this->resourceOption('Memory', 'memory'); + $cpu = $this->resourceOption('CPU', 'cpu'); + DB::table('config_option_products')->insert([ + [ + 'product_id' => $product->id, + 'config_option_id' => $memory->id, + ], + [ + 'product_id' => $product->id, + 'config_option_id' => $cpu->id, + ], + ]); + $plan = Plan::factory()->create([ + 'priceable_id' => $product->id, + 'priceable_type' => Product::class, + 'type' => 'free', + 'billing_unit' => null, + 'billing_period' => 1, + ]); + $cart = new Cart([ + 'currency_code' => 'USD', + ]); + $cart->id = 71; + $cart->exists = true; + $cartItem = new CartItem([ + 'cart_id' => $cart->id, + 'product_id' => $product->id, + 'plan_id' => $plan->id, + 'quantity' => 1, + 'config_options' => [[ + 'option_id' => $memory->id, + 'value' => 4096, + ]], + ]); + $cartItem->setRelation('cart', $cart); + $cartItem->setRelation('product', $product); + $cartItem->setRelation('plan', $plan); + + $stockConfiguration = Mockery::mock( + ProductResourceConfigurationService::class + ); + $stockConfiguration->shouldReceive('forQuote') + ->once() + ->andReturn([ + 'sliders' => [ + 'memory' => ['config_option_id' => $memory->id], + 'cpu' => ['config_option_id' => $cpu->id], + ], + ]); + $this->app->instance( + ProductResourceConfigurationService::class, + $stockConfiguration + ); + + $this->expectException(\App\Exceptions\DisplayException::class); + $this->expectExceptionMessage( + 'Reload checkout and explicitly select every resource again.' + ); + + (new ReservationConfigurationService)->forCartItem($cartItem); + } + public function test_only_one_pending_hold_may_use_a_cart_item_guard(): void { $this->insertReservation(cartItemGuardId: 42); @@ -136,6 +244,48 @@ public function test_only_one_active_hold_may_claim_an_allocation(): void $this->insertAllocation($second, 7001); } + public function test_admin_cancellation_rolls_back_status_when_allocation_release_fails(): void + { + $reservationId = $this->insertReservation(); + $this->insertAllocation($reservationId); + $token = (string) DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('token'); + $service = new class( + $this->nodeService, + $this->configurationService + ) extends ReservationService + { + protected function releaseAllocationClaims( + int $reservationId + ): void { + throw new \RuntimeException( + 'Injected allocation release failure.' + ); + } + }; + + try { + $service->cancel($token, 'Atomic cancellation regression'); + $this->fail('The injected claim release failure must abort cancellation.'); + } catch (\RuntimeException $exception) { + $this->assertSame( + 'Injected allocation release failure.', + $exception->getMessage() + ); + } + + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'pending', + ]); + $this->assertNull( + DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservationId) + ->value('released_at') + ); + } + public function test_reservation_snapshot_is_built_under_the_configuration_lock(): void { $source = file_get_contents( @@ -993,6 +1143,170 @@ public function test_cancellation_tombstone_wins_after_external_create(): void ]); } + public function test_unpinned_paid_cancellation_exposes_only_the_signed_checkout_contract(): void + { + $service = $this->makeService('provisioning'); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed' + ); + $this->insertAllocation($reservationId); + $this->service()->requestServiceCancellation($service); + + $context = $this->service() + ->cancellationReconciliationContext($service); + + $this->assertSame($reservationId, $context['reservation_id']); + $this->assertSame( + (string) $service->id, + $context['external_server_external_id'] + ); + $this->assertSame( + "paymenter-user-{$service->user_id}", + $context['user_external_id'] + ); + $this->assertSame(4, $context['node_id']); + $this->assertSame(4096, $context['memory']); + $this->assertSame(200, $context['cpu']); + $this->assertSame(51200, $context['disk']); + $this->assertSame(0, $context['client_allocation_limit']); + $this->assertFalse($context['provisioning_in_flight']); + $this->assertSame([7001], array_column( + $context['allocations'], + 'allocation_id' + )); + $this->assertMatchesRegularExpression( + '/^[a-f0-9]{64}$/', + $context['configuration_fingerprint'] + ); + } + + public function test_absent_unpinned_server_completes_paid_cancellation(): void + { + $service = $this->makeService('provisioning'); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed' + ); + $this->insertAllocation($reservationId); + $this->service()->requestServiceCancellation($service); + + $this->assertTrue( + $this->service()->completeServiceCancellation($service) + ); + + $this->assertSame( + Service::STATUS_CANCELLED, + $service->fresh()->status + ); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'cancelled', + ]); + $this->assertNotNull( + DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservationId) + ->value('released_at') + ); + } + + public function test_paid_cancellation_context_marks_an_active_create_race(): void + { + $service = $this->makeService('provisioning'); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed', + provisioningStartedAt: now(), + provisioningLeaseId: 'active-create' + ); + $this->insertAllocation($reservationId); + $this->service()->requestServiceCancellation($service); + + $context = $this->service() + ->cancellationReconciliationContext($service); + + $this->assertTrue($context['provisioning_in_flight']); + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('still in flight'); + + $this->service()->pinCancellationServerIdentity( + $service, + $this->cancellationServer($service->id), + 44 + ); + } + + public function test_timed_out_create_identity_is_pinned_idempotently_before_cancellation(): void + { + $service = $this->makeService('provisioning'); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed' + ); + $this->insertAllocation($reservationId); + $this->service()->requestServiceCancellation($service); + $server = $this->cancellationServer($service->id); + + $first = $this->service()->pinCancellationServerIdentity( + $service, + $server, + 44 + ); + $second = $this->service()->pinCancellationServerIdentity( + $service, + $server, + 44 + ); + + $this->assertSame(71, $first['external_server_id']); + $this->assertSame($first, $second); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $reservationId, + 'status' => 'paid_committed', + 'external_server_id' => 71, + 'external_user_id' => 44, + 'external_server_identifier' => 'created', + ]); + } + + public function test_mismatched_timed_out_create_is_never_pinned(): void + { + $service = $this->makeService('provisioning'); + $reservationId = $this->insertReservation( + serviceId: $service->id, + userId: $service->user_id, + status: 'paid_committed' + ); + $this->insertAllocation($reservationId); + $this->service()->requestServiceCancellation($service); + $server = $this->cancellationServer($service->id); + $server['attributes']['limits']['disk']++; + + try { + $this->service()->pinCancellationServerIdentity( + $service, + $server, + 44 + ); + $this->fail('Expected mismatched server rejection.'); + } catch (PermanentProvisioningException $exception) { + $this->assertStringContainsString( + 'reserved disk', + $exception->getMessage() + ); + } + + $this->assertNull( + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('external_server_id') + ); + } + public function test_unpaid_cancellation_returns_product_stock_exactly_once(): void { [$service, $product] = $this->makeStockedService(stock: 4); @@ -2147,8 +2461,14 @@ private function insertReservation( $payload = [ 'customer_id' => $userId, 'cart_id' => $cartId, + 'server_extension_id' => 0, + 'product_id' => (int) $productId, + 'plan_id' => (int) $planId, + 'quantity' => 1, + 'currency_code' => 'USD', 'panel_identity' => str_repeat('c', 64), 'node_id' => 4, + 'location_id' => 2, 'resources' => [ 'memory' => 4096, 'cpu' => 200, @@ -2225,6 +2545,10 @@ private function insertReservation( private function insertAllocation(int $reservationId, int $allocationId = 7001): void { + $status = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('status'); + DB::table('ptero_reservation_allocations')->insert([ 'reservation_id' => $reservationId, 'panel_identity' => str_repeat('c', 64), @@ -2234,6 +2558,7 @@ private function insertAllocation(int $reservationId, int $allocationId = 7001): 'port' => 25565, 'environment_key' => 'SERVER_PORT', 'is_primary' => true, + 'released_at' => $status === 'confirmed' ? now() : null, 'created_at' => now(), 'updated_at' => now(), ]); @@ -2253,4 +2578,40 @@ private function externalServer(): array ], ]; } + + /** + * @return array + */ + private function cancellationServer(int $serviceId): array + { + return [ + 'attributes' => [ + 'id' => 71, + 'uuid' => + '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', + 'identifier' => 'created', + 'external_id' => (string) $serviceId, + 'user' => 44, + 'node' => 4, + 'nest' => 1, + 'egg' => 2, + 'allocation' => 7001, + 'limits' => [ + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 51200, + ], + 'feature_limits' => [ + 'allocations' => 0, + ], + 'relationships' => [ + 'allocations' => [ + 'data' => [[ + 'attributes' => ['id' => 7001], + ]], + ], + ], + ], + ]; + } } diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index c747182..bf9886a 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -6,9 +6,13 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\DB; use Mockery; +use PHPUnit\Framework\Attributes\DataProvider; +use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\NodeCapacityPolicy; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\PterodactylInventoryService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationConfigurationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceCalculationService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\UpgradeReservationIntegrityService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; class ResourceCalculationServiceTest extends LaravelTestCase @@ -139,7 +143,7 @@ public function test_unbounded_node_overallocation_settings_fail_closed(): void } } - public function test_customer_allocation_claims_make_node_ineligible_even_without_headroom(): void + public function test_any_customer_allocation_capability_makes_node_ineligible(): void { $this->createCpuPolicy(); $node = $this->service(servers: [[ @@ -148,14 +152,14 @@ public function test_customer_allocation_claims_make_node_ineligible_even_withou 'memory' => 1024, 'cpu' => 100, 'disk' => 10240, - 'allocation_limit' => 2, - 'assigned_allocation_ids' => [501, 502], + 'allocation_limit' => 1, + 'assigned_allocation_ids' => [501], 'allocation_headroom' => 0, ]])->getLocationAvailability(1)['nodes'][0]; $this->assertFalse($node['eligible']); $this->assertContains( - 'customer_allocation_headroom', + 'customer_allocation_management', $node['ineligible_reasons'] ); } @@ -224,12 +228,12 @@ public function test_pending_and_paid_committed_capacity_is_counted_with_self_ex 'memory' => 2048, 'cpu' => 100, 'disk' => 10240, - ]); + ], purpose: 'checkout'); $this->insertReservation('paid-other', 'paid_committed', [ 'memory' => 1024, 'cpu' => 50, 'disk' => 5120, - ], expiresAt: now()->subDay()); + ], expiresAt: now()->subDay(), purpose: 'checkout'); $node = $this->service() ->getLocationAvailability(1, 'pending-self')['nodes'][0]; @@ -243,26 +247,14 @@ public function test_pending_and_paid_committed_capacity_is_counted_with_self_ex public function test_upgrade_holds_count_only_positive_reserved_deltas(): void { $this->createCpuPolicy(); - DB::table('ptero_resource_reservations')->insert([ - 'purpose' => 'upgrade', - 'token' => 'upgrade-delta', - 'panel_identity' => self::PANEL_IDENTITY, - 'node_id' => 5, - 'location_id' => 1, + $this->insertUpgradeReservation( + 'upgrade-delta', + 'pending', + ['memory' => 6144, 'cpu' => 300, 'disk' => 40960], // Target values must not be double-counted as newly reserved stock. - 'memory' => 8192, - 'cpu' => 400, - 'disk' => 51200, - 'reserved_memory' => 2048, - 'reserved_cpu' => 100, - 'reserved_disk' => 10240, - 'calculated_price' => 9.99, - 'pricing_breakdown' => json_encode([]), - 'status' => 'pending', - 'expires_at' => now()->addMinutes(15), - 'created_at' => now(), - 'updated_at' => now(), - ]); + ['memory' => 8192, 'cpu' => 400, 'disk' => 51200], + ['memory' => 2048, 'cpu' => 100, 'disk' => 10240] + ); $node = $this->service()->getLocationAvailability(1)['nodes'][0]; @@ -273,6 +265,54 @@ public function test_upgrade_holds_count_only_positive_reserved_deltas(): void ], $node['reserved']); } + public function test_upgrade_delta_row_drift_fails_stock_closed(): void + { + $this->createCpuPolicy(); + $reservationId = $this->insertUpgradeReservation( + 'upgrade-delta-drift', + 'pending', + ['memory' => 6144, 'cpu' => 300, 'disk' => 40960], + ['memory' => 8192, 'cpu' => 400, 'disk' => 51200], + ['memory' => 2048, 'cpu' => 100, 'disk' => 10240] + ); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update(['reserved_memory' => 0]); + + $this->expectException(InvalidStockConfigurationException::class); + $this->expectExceptionMessage( + 'upgrade capacity snapshot failed its immutable integrity check' + ); + + $this->service()->getLocationAvailability(1); + } + + public function test_upgrade_invoice_lifecycle_drift_fails_stock_closed(): void + { + $this->createCpuPolicy(); + $reservationId = $this->insertUpgradeReservation( + 'upgrade-invoice-drift', + 'pending', + ['memory' => 6144, 'cpu' => 300, 'disk' => 40960], + ['memory' => 8192, 'cpu' => 400, 'disk' => 51200], + ['memory' => 2048, 'cpu' => 100, 'disk' => 10240] + ); + $invoiceId = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('invoice_id'); + $this->assertNotNull($invoiceId); + DB::table('invoices') + ->where('id', $invoiceId) + ->update(['status' => \App\Models\Invoice::STATUS_PAID]); + + $this->expectException(InvalidStockConfigurationException::class); + $this->expectExceptionMessage( + 'upgrade capacity snapshot failed its immutable integrity check' + ); + + $this->service()->getLocationAvailability(1); + } + public function test_confirmed_checkout_stays_overlaid_until_same_snapshot_proves_target(): void { $this->createCpuPolicy(); @@ -285,7 +325,8 @@ public function test_confirmed_checkout_stays_overlaid_until_same_snapshot_prove $reservationId = $this->insertReservation( 'confirmed-checkout-overlay', 'confirmed', - ['memory' => 4096, 'cpu' => 200, 'disk' => 20480] + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480], + purpose: 'checkout' ); DB::table('ptero_resource_reservations') ->where('id', $reservationId) @@ -334,7 +375,8 @@ public function test_confirmed_upgrade_supersedes_checkout_and_overlays_only_sna $checkoutId = $this->insertReservation( 'confirmed-checkout-before-upgrade', 'confirmed', - ['memory' => 4096, 'cpu' => 200, 'disk' => 20480] + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480], + purpose: 'checkout' ); DB::table('ptero_resource_reservations') ->where('id', $checkoutId) @@ -347,24 +389,16 @@ public function test_confirmed_upgrade_supersedes_checkout_and_overlays_only_sna 'external_server_identifier' => 'server-81', 'consumed_at' => now()->subHour(), ]); - $upgradeId = $this->insertReservation( + $this->insertUpgradeReservation( 'confirmed-upgrade-target', 'confirmed', - ['memory' => 8192, 'cpu' => 400, 'disk' => 40960] + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480], + ['memory' => 8192, 'cpu' => 400, 'disk' => 40960], + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480], + service: $serviceRecord, + externalServerId: 81, + consumedAt: now() ); - DB::table('ptero_resource_reservations') - ->where('id', $upgradeId) - ->update([ - 'purpose' => 'upgrade', - 'service_id' => $serviceRecord->id, - 'configuration_payload' => json_encode([ - 'external_server_id' => 81, - ]), - 'reserved_memory' => 4096, - 'reserved_cpu' => 200, - 'reserved_disk' => 20480, - 'consumed_at' => now(), - ]); $reflected = $this->service(servers: [[ 'id' => 81, @@ -398,7 +432,7 @@ public function test_confirmed_upgrade_supersedes_checkout_and_overlays_only_sna ); } - public function test_multiple_confirmed_upgrades_keep_only_latest_target(): void + public function test_multiple_confirmed_upgrades_use_immutable_upgrade_order_not_mutable_timestamps(): void { $this->createCpuPolicy(); $serviceRecord = \App\Models\Service::factory()->create([ @@ -408,53 +442,42 @@ public function test_multiple_confirmed_upgrades_keep_only_latest_target(): void 'status' => \App\Models\Service::STATUS_ACTIVE, ]); - foreach ([ - [ - 'token' => 'confirmed-base', - 'purpose' => 'checkout', - 'resources' => [4096, 200, 20480], + $checkoutId = $this->insertReservation( + 'confirmed-base', + 'confirmed', + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480], + purpose: 'checkout' + ); + DB::table('ptero_resource_reservations') + ->where('id', $checkoutId) + ->update([ + 'service_id' => $serviceRecord->id, + 'external_server_id' => 81, + 'external_server_uuid' => + '10000000-0000-4000-8000-000000000081', + 'external_server_identifier' => 'server-81', 'consumed_at' => now()->subHours(2), - ], - [ - 'token' => 'confirmed-upgrade-eight', - 'purpose' => 'upgrade', - 'resources' => [8192, 400, 40960], - 'consumed_at' => now()->subHour(), - ], - [ - 'token' => 'confirmed-upgrade-six', - 'purpose' => 'upgrade', - 'resources' => [6144, 300, 30720], - 'consumed_at' => now(), - ], - ] as $expectation) { - [$memory, $cpu, $disk] = $expectation['resources']; - $reservationId = $this->insertReservation( - $expectation['token'], - 'confirmed', - compact('memory', 'cpu', 'disk') - ); - DB::table('ptero_resource_reservations') - ->where('id', $reservationId) - ->update([ - 'purpose' => $expectation['purpose'], - 'service_id' => $serviceRecord->id, - 'external_server_id' => - $expectation['purpose'] === 'checkout' ? 81 : null, - 'external_server_uuid' => - $expectation['purpose'] === 'checkout' - ? '10000000-0000-4000-8000-000000000081' - : null, - 'external_server_identifier' => - $expectation['purpose'] === 'checkout' - ? 'server-81' - : null, - 'configuration_payload' => json_encode([ - 'external_server_id' => 81, - ]), - 'consumed_at' => $expectation['consumed_at'], - ]); - } + ]); + $this->insertUpgradeReservation( + 'confirmed-upgrade-eight', + 'confirmed', + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480], + ['memory' => 8192, 'cpu' => 400, 'disk' => 40960], + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480], + service: $serviceRecord, + externalServerId: 81, + consumedAt: now() + ); + $this->insertUpgradeReservation( + 'confirmed-upgrade-six', + 'confirmed', + ['memory' => 8192, 'cpu' => 400, 'disk' => 40960], + ['memory' => 6144, 'cpu' => 300, 'disk' => 40960], + ['memory' => 0, 'cpu' => 0, 'disk' => 0], + service: $serviceRecord, + externalServerId: 81, + consumedAt: now()->subDay() + ); $node = $this->service(servers: [[ 'id' => 81, @@ -464,7 +487,7 @@ public function test_multiple_confirmed_upgrades_keep_only_latest_target(): void 'node' => 5, 'memory' => 6144, 'cpu' => 300, - 'disk' => 30720, + 'disk' => 40960, ]])->getLocationAvailability(1)['nodes'][0]; $this->assertSame( @@ -485,7 +508,8 @@ public function test_conflicting_confirmed_server_identities_fail_snapshot_proof $checkoutId = $this->insertReservation( 'identity-checkout', 'confirmed', - ['memory' => 4096, 'cpu' => 200, 'disk' => 20480] + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480], + purpose: 'checkout' ); DB::table('ptero_resource_reservations') ->where('id', $checkoutId) @@ -495,21 +519,16 @@ public function test_conflicting_confirmed_server_identities_fail_snapshot_proof 'external_server_id' => 81, 'consumed_at' => now()->subHour(), ]); - $upgradeId = $this->insertReservation( + $this->insertUpgradeReservation( 'identity-upgrade', 'confirmed', - ['memory' => 8192, 'cpu' => 400, 'disk' => 40960] + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480], + ['memory' => 8192, 'cpu' => 400, 'disk' => 40960], + ['memory' => 4096, 'cpu' => 200, 'disk' => 20480], + service: $serviceRecord, + externalServerId: 82, + consumedAt: now() ); - DB::table('ptero_resource_reservations') - ->where('id', $upgradeId) - ->update([ - 'purpose' => 'upgrade', - 'service_id' => $serviceRecord->id, - 'configuration_payload' => json_encode([ - 'external_server_id' => 82, - ]), - 'consumed_at' => now(), - ]); $node = $this->service(servers: [[ 'id' => 82, @@ -566,7 +585,15 @@ public function test_confirmed_local_claim_blocks_a_stale_free_allocation_snapsh $reservationId = $this->insertReservation( 'confirmed-allocation-claim', 'confirmed', - ['memory' => 1024, 'cpu' => 100, 'disk' => 10240] + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + purpose: 'checkout', + allocation: [ + 'allocation_id' => 501, + 'ip' => '192.0.2.5', + 'port' => 25565, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ] ); DB::table('ptero_resource_reservations') ->where('id', $reservationId) @@ -575,19 +602,6 @@ public function test_confirmed_local_claim_blocks_a_stale_free_allocation_snapsh 'external_server_id' => 81, 'consumed_at' => now(), ]); - DB::table('ptero_reservation_allocations')->insert([ - 'reservation_id' => $reservationId, - 'panel_identity' => self::PANEL_IDENTITY, - 'node_id' => 5, - 'allocation_id' => 501, - 'ip' => '192.0.2.5', - 'port' => 25565, - 'is_primary' => true, - 'released_at' => now(), - 'created_at' => now(), - 'updated_at' => now(), - ]); - $node = $this->service(allocations: [ ['id' => 501, 'ip' => '192.0.2.5', 'port' => 25565], ['id' => 502, 'ip' => '192.0.2.6', 'port' => 25566], @@ -602,22 +616,19 @@ public function test_confirmed_local_claim_blocks_a_stale_free_allocation_snapsh public function test_locally_reserved_allocation_is_removed_from_panel_unassigned_inventory(): void { $this->createCpuPolicy(); - $reservationId = $this->insertReservation('allocation-hold', 'pending', [ - 'memory' => 1024, - 'cpu' => 100, - 'disk' => 10240, - ]); - DB::table('ptero_reservation_allocations')->insert([ - 'reservation_id' => $reservationId, - 'panel_identity' => self::PANEL_IDENTITY, - 'node_id' => 5, - 'allocation_id' => 502, - 'ip' => '192.0.2.5', - 'port' => 25566, - 'is_primary' => true, - 'created_at' => now(), - 'updated_at' => now(), - ]); + $this->insertReservation( + 'allocation-hold', + 'pending', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + purpose: 'checkout', + allocation: [ + 'allocation_id' => 502, + 'ip' => '192.0.2.5', + 'port' => 25566, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ] + ); $service = $this->service(allocations: [ ['id' => 501, 'ip' => '192.0.2.5', 'port' => 25565], @@ -645,19 +656,16 @@ public function test_equivalent_ipv6_reservation_marks_the_whole_ip_in_use(): vo $reservationId = $this->insertReservation( 'ipv6-allocation-hold', 'pending', - ['memory' => 1024, 'cpu' => 100, 'disk' => 10240] + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + purpose: 'checkout', + allocation: [ + 'allocation_id' => 601, + 'ip' => '2001:db8::1', + 'port' => 25565, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ] ); - DB::table('ptero_reservation_allocations')->insert([ - 'reservation_id' => $reservationId, - 'panel_identity' => self::PANEL_IDENTITY, - 'node_id' => 5, - 'allocation_id' => 601, - 'ip' => '2001:db8::1', - 'port' => 25565, - 'is_primary' => true, - 'created_at' => now(), - 'updated_at' => now(), - ]); $node = $this->service(allocations: [[ 'id' => 602, @@ -671,29 +679,20 @@ public function test_equivalent_ipv6_reservation_marks_the_whole_ip_in_use(): vo public function test_pending_dedicated_hold_removes_its_whole_ip_from_all_stock(): void { $this->createCpuPolicy(); - $reservationId = $this->insertReservation( + $this->insertReservation( 'dedicated-allocation-hold', 'pending', - ['memory' => 1024, 'cpu' => 100, 'disk' => 10240] + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + purpose: 'checkout', + allocation: [ + 'allocation_id' => 502, + 'ip' => '192.0.2.5', + 'port' => 25566, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ], + dedicatedIp: true ); - DB::table('ptero_resource_reservations') - ->where('id', $reservationId) - ->update([ - 'configuration_payload' => json_encode([ - 'allocation_requirements' => ['dedicated_ip' => true], - ]), - ]); - DB::table('ptero_reservation_allocations')->insert([ - 'reservation_id' => $reservationId, - 'panel_identity' => self::PANEL_IDENTITY, - 'node_id' => 5, - 'allocation_id' => 502, - 'ip' => '192.0.2.5', - 'port' => 25566, - 'is_primary' => true, - 'created_at' => now(), - 'updated_at' => now(), - ]); $service = $this->service(allocations: [ ['id' => 501, 'ip' => '192.0.2.5', 'port' => 25565], ['id' => 502, 'ip' => '192.0.2.5', 'port' => 25566], @@ -714,6 +713,291 @@ public function test_pending_dedicated_hold_removes_its_whole_ip_from_all_stock( ); } + public function test_tampered_dedicated_ip_claim_fails_stock_closed(): void + { + $this->createCpuPolicy(); + $reservationId = $this->insertReservation( + 'tampered-dedicated-allocation-hold', + 'pending', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + purpose: 'checkout', + allocation: [ + 'allocation_id' => 502, + 'ip' => '192.0.2.5', + 'port' => 25566, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ], + dedicatedIp: true + ); + $tampered = json_decode( + (string) DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('configuration_payload'), + true, + 512, + JSON_THROW_ON_ERROR + ); + $tampered['allocation_requirements']['dedicated_ip'] = false; + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'configuration_payload' => json_encode( + $tampered, + JSON_THROW_ON_ERROR + ), + ]); + + $this->expectException(InvalidStockConfigurationException::class); + $this->expectExceptionMessage( + 'allocation snapshot failed its immutable capacity integrity check' + ); + + $this->service(allocations: [ + ['id' => 501, 'ip' => '192.0.2.5', 'port' => 25565], + ['id' => 502, 'ip' => '192.0.2.5', 'port' => 25566], + ])->getLocationAvailability(1); + } + + public function test_missing_checkout_allocation_claim_fails_stock_closed_even_when_self_excluded(): void + { + $this->createCpuPolicy(); + $reservationId = $this->insertReservation( + 'missing-self-claim', + 'pending', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + purpose: 'checkout' + ); + DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservationId) + ->delete(); + + $this->expectException(InvalidStockConfigurationException::class); + $this->expectExceptionMessage( + 'Allocation claims no longer match the immutable checkout reservation' + ); + + $this->service()->getLocationAvailability( + 1, + 'missing-self-claim' + ); + } + + #[DataProvider('allocationClaimDriftCases')] + public function test_each_checkout_allocation_tuple_field_is_verified( + string $field, + mixed $value + ): void { + $this->createCpuPolicy(); + $reservationId = $this->insertReservation( + "claim-drift-{$field}", + 'pending', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + purpose: 'checkout', + allocation: [ + 'allocation_id' => 502, + 'ip' => '192.0.2.5', + 'port' => 25566, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ] + ); + DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservationId) + ->update([$field => $value]); + + $this->expectException(InvalidStockConfigurationException::class); + $this->expectExceptionMessage( + 'Allocation claims no longer match the immutable checkout reservation' + ); + + $this->service()->getLocationAvailability(1); + } + + public function test_extra_checkout_allocation_claim_fails_stock_closed(): void + { + $this->createCpuPolicy(); + $reservationId = $this->insertReservation( + 'extra-claim', + 'pending', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + purpose: 'checkout' + ); + DB::table('ptero_reservation_allocations')->insert([ + 'reservation_id' => $reservationId, + 'panel_identity' => self::PANEL_IDENTITY, + 'node_id' => 5, + 'allocation_id' => 991001, + 'ip' => '192.0.2.99', + 'port' => 29999, + 'environment_key' => 'QUERY_PORT', + 'is_primary' => false, + 'created_at' => now(), + 'updated_at' => now(), + ]); + + $this->expectException(InvalidStockConfigurationException::class); + $this->expectExceptionMessage( + 'Allocation claims no longer match the immutable checkout reservation' + ); + + $this->service()->getLocationAvailability(1); + } + + #[DataProvider('activeClaimStatuses')] + public function test_pending_and_paid_claims_must_remain_unreleased( + string $status + ): void { + $this->createCpuPolicy(); + $reservationId = $this->insertReservation( + "released-{$status}", + $status, + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + expiresAt: $status === 'paid_committed' + ? now()->subDay() + : now()->addDay(), + purpose: 'checkout' + ); + DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservationId) + ->update(['released_at' => now()]); + + $this->expectException(InvalidStockConfigurationException::class); + $this->expectExceptionMessage( + 'Allocation claims no longer match the immutable checkout reservation' + ); + + $this->service()->getLocationAvailability(1); + } + + public function test_confirmed_claim_must_be_released_before_stock_can_be_quoted(): void + { + $this->createCpuPolicy(); + $reservationId = $this->insertReservation( + 'confirmed-unreleased', + 'confirmed', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + purpose: 'checkout' + ); + DB::table('ptero_reservation_allocations') + ->where('reservation_id', $reservationId) + ->update(['released_at' => null]); + + $this->expectException(InvalidStockConfigurationException::class); + $this->expectExceptionMessage( + 'Allocation claims no longer match the immutable checkout reservation' + ); + + $this->service()->getLocationAvailability(1); + } + + public function test_expired_pending_commitment_stays_counted_until_atomic_cleanup(): void + { + $this->createCpuPolicy(); + $this->insertReservation( + 'pending-awaiting-cleanup', + 'pending', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + expiresAt: now()->subMinute(), + purpose: 'checkout' + ); + + $node = $this->service()->getLocationAvailability(1)['nodes'][0]; + + $this->assertSame( + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + $node['reserved'] + ); + $this->assertSame([], $node['available_allocations']); + } + + public function test_materialized_terminal_commitment_with_unreleased_claim_fails_stock_closed(): void + { + $this->createCpuPolicy(); + $this->insertReservation( + 'expired-unreleased', + 'expired', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + expiresAt: now()->subMinute(), + purpose: 'checkout' + ); + + $this->expectException(InvalidStockConfigurationException::class); + $this->expectExceptionMessage( + 'terminal capacity commitment still owns an unreleased allocation claim' + ); + + $this->service()->getLocationAvailability(1); + } + + public function test_upgrade_commitment_cannot_own_checkout_allocation_claims(): void + { + $this->createCpuPolicy(); + $reservationId = $this->insertReservation( + 'upgrade-with-claim', + 'pending', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + purpose: 'upgrade' + ); + DB::table('ptero_reservation_allocations')->insert([ + 'reservation_id' => $reservationId, + 'panel_identity' => self::PANEL_IDENTITY, + 'node_id' => 5, + 'allocation_id' => 991002, + 'ip' => '192.0.2.100', + 'port' => 30000, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + 'created_at' => now(), + 'updated_at' => now(), + ]); + + $this->expectException(InvalidStockConfigurationException::class); + $this->expectExceptionMessage( + 'resource upgrade unexpectedly owns checkout allocation claims' + ); + + $this->service()->getLocationAvailability(1); + } + + public function test_signed_required_allocation_count_must_match_claim_set(): void + { + $this->createCpuPolicy(); + $reservationId = $this->insertReservation( + 'required-count-drift', + 'pending', + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + purpose: 'checkout' + ); + $payload = json_decode( + (string) DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('configuration_payload'), + true, + 512, + JSON_THROW_ON_ERROR + ); + $payload['allocation_requirements']['required_count'] = 2; + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + 'configuration_fingerprint' => + (new ReservationConfigurationService) + ->fingerprint($payload), + ]); + + $this->expectException(InvalidStockConfigurationException::class); + $this->expectExceptionMessage( + 'no valid signed allocation set' + ); + + $this->service()->getLocationAvailability(1); + } + public function test_confirmed_dedicated_server_blocks_ip_until_service_is_cancelled(): void { $this->createCpuPolicy(); @@ -726,28 +1010,22 @@ public function test_confirmed_dedicated_server_blocks_ip_until_service_is_cance $reservationId = $this->insertReservation( 'confirmed-dedicated', 'confirmed', - ['memory' => 1024, 'cpu' => 100, 'disk' => 10240] + ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], + purpose: 'checkout', + allocation: [ + 'allocation_id' => 501, + 'ip' => '192.0.2.5', + 'port' => 25565, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ], + dedicatedIp: true ); DB::table('ptero_resource_reservations') ->where('id', $reservationId) ->update([ 'service_id' => $serviceRecord->id, - 'configuration_payload' => json_encode([ - 'allocation_requirements' => ['dedicated_ip' => true], - ]), ]); - DB::table('ptero_reservation_allocations')->insert([ - 'reservation_id' => $reservationId, - 'panel_identity' => self::PANEL_IDENTITY, - 'node_id' => 5, - 'allocation_id' => 501, - 'ip' => '192.0.2.5', - 'port' => 25565, - 'is_primary' => true, - 'released_at' => now(), - 'created_at' => now(), - 'updated_at' => now(), - ]); $stock = $this->service(allocations: [ ['id' => 502, 'ip' => '192.0.2.5', 'port' => 25566], ['id' => 503, 'ip' => '192.0.2.6', 'port' => 25565], @@ -776,23 +1054,20 @@ public function test_confirmed_dedicated_server_blocks_ip_until_service_is_cance public function test_holds_from_another_panel_do_not_reduce_colliding_node_or_allocation_stock(): void { $this->createCpuPolicy(); - $reservationId = $this->insertReservation( + $this->insertReservation( 'other-panel-hold', 'pending', ['memory' => 2048, 'cpu' => 100, 'disk' => 10240], - panelIdentity: str_repeat('f', 64) + panelIdentity: str_repeat('f', 64), + purpose: 'checkout', + allocation: [ + 'allocation_id' => 501, + 'ip' => '192.0.2.5', + 'port' => 25565, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ] ); - DB::table('ptero_reservation_allocations')->insert([ - 'reservation_id' => $reservationId, - 'panel_identity' => str_repeat('f', 64), - 'node_id' => 5, - 'allocation_id' => 501, - 'ip' => '192.0.2.5', - 'port' => 25565, - 'is_primary' => true, - 'created_at' => now(), - 'updated_at' => now(), - ]); $node = $this->service()->getLocationAvailability(1)['nodes'][0]; @@ -905,16 +1180,335 @@ private function createCpuPolicy( ]); } + /** + * @return array + */ + public static function allocationClaimDriftCases(): array + { + return [ + 'panel' => ['panel_identity', str_repeat('f', 64)], + 'node' => ['node_id', 6], + 'allocation' => ['allocation_id', 503], + 'ip' => ['ip', '192.0.2.6'], + 'port' => ['port', 25567], + 'environment' => ['environment_key', 'QUERY_PORT'], + 'primary' => ['is_primary', false], + ]; + } + + /** + * @return array + */ + public static function activeClaimStatuses(): array + { + return [ + 'pending' => ['pending'], + 'paid committed' => ['paid_committed'], + ]; + } + + private function insertUpgradeReservation( + string $token, + string $status, + array $source, + array $target, + array $delta, + ?\App\Models\Service $service = null, + int $externalServerId = 81, + mixed $consumedAt = null + ): int { + if ( + $service === null + || $service->product_id === null + || $service->plan_id === null + ) { + $product = \App\Models\Product::factory()->create(); + $plan = \App\Models\Plan::factory()->create([ + 'priceable_id' => $product->id, + 'priceable_type' => \App\Models\Product::class, + ]); + $service ??= \App\Models\Service::factory()->create([ + 'user_id' => User::factory()->create()->id, + ]); + DB::table('services')->where('id', $service->id)->update([ + 'product_id' => $product->id, + 'plan_id' => $plan->id, + 'quantity' => 1, + 'currency_code' => 'USD', + ]); + $service->refresh(); + } + $product = \App\Models\Product::query() + ->findOrFail($service->product_id); + $server = $product->server; + if ($server?->extension !== 'Pterodactyl') { + $server = \App\Models\Server::query()->create([ + 'name' => "Pterodactyl Upgrade {$token}", + 'extension' => 'Pterodactyl', + 'type' => 'server', + 'enabled' => true, + ]); + DB::table('products') + ->where('id', $service->product_id) + ->update(['server_id' => $server->id]); + } + $sourceSnapshot = [ + 'service_id' => (int) $service->id, + 'product_id' => (int) $service->product_id, + 'plan_id' => (int) $service->plan_id, + 'quantity' => 1, + 'currency_code' => 'USD', + 'properties' => [ + ...$source, + 'location' => 1, + ], + 'billing_anchor' => [], + ]; + $targetSnapshot = [ + 'service_id' => (int) $service->id, + 'product_id' => (int) $service->product_id, + 'plan_id' => (int) $service->plan_id, + 'quantity' => 1, + 'currency_code' => 'USD', + 'properties' => [ + ...$target, + 'location' => 1, + ], + 'recurring_price' => '0.00', + 'billing_anchor' => [], + ]; + $invoice = \App\Models\Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => match ($status) { + 'pending' => \App\Models\Invoice::STATUS_PENDING, + 'paid_committed', + 'confirmed' => \App\Models\Invoice::STATUS_PAID, + default => throw new \InvalidArgumentException( + "Unsupported upgrade reservation status {$status}." + ), + }, + 'currency_code' => 'USD', + ]); + $sourceFingerprint = $this->serviceUpgradeSnapshotFingerprint( + $sourceSnapshot + ); + $targetFingerprint = $this->serviceUpgradeSnapshotFingerprint( + $targetSnapshot + ); + $upgradeId = DB::table('service_upgrades')->insertGetId([ + 'service_id' => $service->id, + 'product_id' => $service->product_id, + 'plan_id' => $service->plan_id, + 'invoice_id' => $invoice->id, + 'status' => match ($status) { + 'confirmed' => 'completed', + 'paid_committed' => 'paid_committed', + 'pending' => 'awaiting_payment', + default => throw new \InvalidArgumentException( + "Unsupported upgrade reservation status {$status}." + ), + }, + 'active_service_guard_id' => $status === 'confirmed' + ? null + : $service->id, + 'type' => 'config_options', + 'source_snapshot' => json_encode( + $sourceSnapshot, + JSON_THROW_ON_ERROR | JSON_PRESERVE_ZERO_FRACTION + ), + 'target_snapshot' => json_encode( + $targetSnapshot, + JSON_THROW_ON_ERROR | JSON_PRESERVE_ZERO_FRACTION + ), + 'source_fingerprint' => $sourceFingerprint, + 'target_fingerprint' => $targetFingerprint, + 'quoted_amount' => '9.90', + 'currency_code' => 'USD', + 'credit_amount' => 0, + 'provisioning_attempts' => 0, + 'created_at' => now(), + 'updated_at' => now(), + ]); + $payload = [ + 'service_upgrade_id' => $upgradeId, + 'source_fingerprint' => $sourceFingerprint, + 'target_fingerprint' => $targetFingerprint, + 'panel_identity' => self::PANEL_IDENTITY, + 'node_id' => 5, + 'location_id' => 1, + 'external_server_id' => $externalServerId, + 'external_server_uuid' => + sprintf( + '10000000-0000-4000-8000-%012d', + $externalServerId + ), + 'external_server_identifier' => + "server-{$externalServerId}", + 'external_server_external_id' => (string) $service->id, + 'external_user_id' => 44, + 'user_external_id' => + "paymenter-user-{$service->user_id}", + 'user_email' => (string) $service->user->email, + 'nest_id' => 1, + 'egg_id' => 2, + 'preserved_build' => [ + 'swap' => 0, + 'io' => 500, + 'threads' => null, + 'databases' => 0, + 'allocations' => 0, + 'backups' => 0, + ], + 'allocation_id' => 501, + 'assigned_allocation_ids' => [501], + 'source' => $source, + 'target' => $target, + 'delta' => $delta, + ]; + $upgrade = (object) [ + 'id' => $upgradeId, + 'service_id' => $service->id, + 'source_fingerprint' => $sourceFingerprint, + 'target_fingerprint' => $targetFingerprint, + 'quoted_amount' => '9.90', + 'currency_code' => 'USD', + ]; + + return DB::table('ptero_resource_reservations')->insertGetId([ + 'purpose' => 'upgrade', + 'token' => $token, + 'service_id' => $service->id, + 'service_upgrade_id' => $upgradeId, + 'upgrade_guard_id' => $status === 'confirmed' + ? null + : $upgradeId, + 'server_extension_id' => $server->id, + 'invoice_id' => $invoice->id, + 'user_id' => $service->user_id, + 'product_id' => $service->product_id, + 'plan_id' => $service->plan_id, + 'quantity' => 1, + 'currency_code' => 'USD', + 'panel_identity' => self::PANEL_IDENTITY, + 'configuration_fingerprint' => + (new UpgradeReservationIntegrityService) + ->fingerprint($upgrade, $payload), + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + 'pricing_version' => + (new UpgradeReservationIntegrityService) + ->pricingVersion($upgrade), + 'formula_version' => 'dynamic-upgrade-v1', + 'node_id' => 5, + 'location_id' => 1, + 'memory' => $target['memory'], + 'cpu' => $target['cpu'], + 'disk' => $target['disk'], + 'reserved_memory' => $delta['memory'], + 'reserved_cpu' => $delta['cpu'], + 'reserved_disk' => $delta['disk'], + 'external_server_id' => $externalServerId, + 'external_user_id' => 44, + 'external_server_uuid' => + $payload['external_server_uuid'], + 'external_server_identifier' => + $payload['external_server_identifier'], + 'calculated_price' => '9.90', + 'pricing_breakdown' => json_encode( + [], + JSON_THROW_ON_ERROR + ), + 'status' => $status, + 'expires_at' => now()->addDay(), + 'consumed_at' => $consumedAt, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + + /** + * @param array $snapshot + */ + private function serviceUpgradeSnapshotFingerprint( + array $snapshot + ): string { + $canonicalize = function (array $value) use ( + &$canonicalize + ): array { + foreach ($value as $key => $item) { + if (is_array($item)) { + $value[$key] = $canonicalize($item); + } + } + if (! array_is_list($value)) { + ksort($value); + } + + return $value; + }; + + return hash('sha256', json_encode( + $canonicalize($snapshot), + JSON_THROW_ON_ERROR + | JSON_PRESERVE_ZERO_FRACTION + | JSON_UNESCAPED_SLASHES + )); + } + private function insertReservation( string $token, string $status, array $resources, mixed $expiresAt = null, - string $panelIdentity = self::PANEL_IDENTITY + string $panelIdentity = self::PANEL_IDENTITY, + string $purpose = 'checkout', + ?array $allocation = null, + bool $dedicatedIp = false ): int { - return DB::table('ptero_resource_reservations')->insertGetId([ + if (! in_array($purpose, ['checkout', 'upgrade'], true)) { + throw new \InvalidArgumentException( + 'The test reservation purpose is invalid.' + ); + } + + $allocation ??= [ + 'allocation_id' => + 100000 + (int) sprintf('%u', crc32($token)), + 'ip' => '198.51.100.10', + 'port' => + 20000 + ((int) sprintf('%u', crc32($token)) % 40000), + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ]; + $payload = $purpose === 'checkout' + ? [ + 'panel_identity' => $panelIdentity, + 'node_id' => 5, + 'location_id' => 1, + 'resources' => $resources, + 'allocation_requirements' => [ + 'required_count' => 1, + 'dedicated_ip' => $dedicatedIp, + ], + 'allocations' => [$allocation], + ] + : []; + + $reservationId = DB::table( + 'ptero_resource_reservations' + )->insertGetId([ + 'purpose' => $purpose, 'token' => $token, 'panel_identity' => $panelIdentity, + 'configuration_fingerprint' => + (new ReservationConfigurationService) + ->fingerprint($payload), + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), 'node_id' => 5, 'location_id' => 1, 'memory' => $resources['memory'], @@ -927,5 +1521,23 @@ private function insertReservation( 'created_at' => now(), 'updated_at' => now(), ]); + + if ($purpose === 'checkout') { + DB::table('ptero_reservation_allocations')->insert([ + 'reservation_id' => $reservationId, + 'panel_identity' => $panelIdentity, + 'node_id' => 5, + 'allocation_id' => $allocation['allocation_id'], + 'ip' => $allocation['ip'], + 'port' => $allocation['port'], + 'environment_key' => $allocation['environment_key'], + 'is_primary' => $allocation['is_primary'], + 'released_at' => $status === 'confirmed' ? now() : null, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + + return $reservationId; } } diff --git a/tests/Unit/UpgradeReservationServiceTest.php b/tests/Unit/UpgradeReservationServiceTest.php index 0dc572d..47567c2 100644 --- a/tests/Unit/UpgradeReservationServiceTest.php +++ b/tests/Unit/UpgradeReservationServiceTest.php @@ -20,12 +20,14 @@ use App\Models\Server; use App\Models\User; use App\Services\Service\CapacityServiceCreationCoordinator; +use App\Services\ServiceUpgrade\ServiceUpgradeService; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Queue; use Mockery; use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidResourceSelectionException; use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException; +use Paymenter\Extensions\Others\DynamicPterodactyl\Models\NodeCapacityPolicy; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\PterodactylInventoryService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationConfigurationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceCalculationService; @@ -216,6 +218,34 @@ public function test_duplicate_active_resource_slider_fails_closed_but_hidden_on $this->assertSame(23552, $quote['bounds']['memory']['max']); } + public function test_zero_resource_minimum_cannot_become_an_unlimited_upgrade(): void + { + $fixture = $this->fixture(); + $metadata = (array) $fixture->options['memory']->metadata; + $metadata['min'] = 0; + $metadata['default'] = 0; + DB::table('config_options') + ->where('id', $fixture->options['memory']->id) + ->update([ + 'metadata' => json_encode( + $metadata, + JSON_THROW_ON_ERROR + ), + ]); + + $this->expectException( + InvalidStockConfigurationException::class + ); + $this->expectExceptionMessage( + 'Memory min value must be a positive whole number.' + ); + + $fixture->upgrades->quoteForService( + $fixture->service, + $this->selection($fixture) + ); + } + public function test_upgrade_reserves_only_positive_delta_but_keeps_full_target(): void { $fixture = $this->fixture(); @@ -246,6 +276,180 @@ public function test_upgrade_reserves_only_positive_delta_but_keeps_full_target( ); } + public function test_second_slider_upgrade_uses_current_service_without_rewriting_checkout_identity(): void + { + Queue::fake(); + $fixture = $this->fixture(); + $checkoutBefore = DB::table('ptero_resource_reservations') + ->where('id', $fixture->checkoutReservationId) + ->first([ + 'configuration_payload', + 'configuration_fingerprint', + 'product_id', + 'plan_id', + ]); + [$firstUpgrade, $firstInvoice] = $this->upgrade($fixture); + $firstReservation = $fixture->upgrades->reserveForUpgrade( + $firstUpgrade, + $firstInvoice->due_at + ); + DB::table('invoices') + ->where('id', $firstInvoice->id) + ->update(['status' => Invoice::STATUS_PAID]); + $fixture->upgrades->commitPaidUpgrade( + $firstUpgrade, + $firstInvoice->fresh() + ); + $provisioningUpgrade = app(ServiceUpgradeService::class) + ->beginProvisioning($firstUpgrade->fresh()); + $contract = $fixture->upgrades->beginProvisioning( + $provisioningUpgrade + ); + $fixture->remote->server['memory'] = 8192; + $fixture->remote->server['cpu'] = 100; + $fixture->remote->server['disk'] = 30720; + + app(ServiceUpgradeService::class)->complete( + $provisioningUpgrade, + $contract['provisioning_lease_id'] + ); + + $this->assertSame( + ServiceUpgrade::STATUS_COMPLETED, + $firstUpgrade->fresh()->status + ); + $this->assertSame( + 'confirmed', + $firstReservation->fresh()->status + ); + $checkoutAfterFirst = DB::table( + 'ptero_resource_reservations' + ) + ->where('id', $fixture->checkoutReservationId) + ->first([ + 'configuration_payload', + 'configuration_fingerprint', + 'product_id', + 'plan_id', + ]); + $this->assertEquals($checkoutBefore, $checkoutAfterFirst); + + $fixture->service->refresh(); + [$secondUpgrade, $secondInvoice] = $this->upgrade($fixture); + foreach ([ + 'memory' => 12288, + 'cpu' => 200, + 'disk' => 40960, + ] as $resource => $value) { + $secondUpgrade->configs() + ->where( + 'config_option_id', + $fixture->options[$resource]->id + ) + ->update(['slider_value' => $value]); + } + $this->recaptureUpgrade($secondUpgrade); + + $secondReservation = $fixture->upgrades->reserveForUpgrade( + $secondUpgrade->fresh(), + $secondInvoice->due_at + ); + $payload = (array) $secondReservation->configuration_payload; + + $this->assertSame([ + 'memory' => 8192, + 'cpu' => 100, + 'disk' => 30720, + ], $payload['source']); + $this->assertSame([ + 'memory' => 12288, + 'cpu' => 200, + 'disk' => 40960, + ], $payload['target']); + $this->assertSame( + $fixture->product->id, + $secondUpgrade->fresh()->product_id + ); + $this->assertSame( + $fixture->plan->id, + $secondUpgrade->fresh()->plan_id + ); + $checkoutAfterSecond = DB::table( + 'ptero_resource_reservations' + ) + ->where('id', $fixture->checkoutReservationId) + ->first([ + 'configuration_payload', + 'configuration_fingerprint', + 'product_id', + 'plan_id', + ]); + $this->assertEquals($checkoutBefore, $checkoutAfterSecond); + } + + public function test_real_upgrade_reservation_is_accepted_by_stock_calculation_across_decimal_drivers(): void + { + $fixture = $this->fixture(); + NodeCapacityPolicy::create([ + 'panel_identity' => + hash('sha256', 'https://panel.example'), + 'node_uuid' => 'node-1', + 'node_id' => 1, + 'location_id' => 1, + 'cpu_capacity_percent' => 800, + 'cpu_overcommit_bps' => 10000, + 'enabled' => true, + ]); + [$upgrade, $invoice] = $this->upgrade($fixture); + $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + + $node = [ + 'id' => 1, + 'uuid' => 'node-1', + 'name' => 'Node 1', + 'fqdn' => 'node-1.example.com', + 'public' => true, + 'maintenance_mode' => false, + 'location_id' => 1, + 'memory' => 32768, + 'disk' => 512000, + 'memory_overallocate' => 0, + 'disk_overallocate' => 0, + 'allocated_resources' => [ + 'memory' => 4096, + 'disk' => 20480, + ], + ]; + $fixture->inventory->shouldReceive('nodesInLocation') + ->once() + ->with(1) + ->andReturn([$node]); + $fixture->inventory->shouldReceive('serversForNodes') + ->once() + ->with([1]) + ->andReturn([1 => [$fixture->remote->server]]); + $fixture->inventory->shouldReceive( + 'availableAllocationsForNode' + )->once()->with(1)->andReturn([[ + 'id' => 9001, + 'ip' => '192.0.2.250', + 'port' => 25566, + ]]); + + $availability = (new ResourceCalculationService( + $fixture->inventory + ))->getLocationAvailability(1); + + $this->assertSame([ + 'memory' => 4096, + 'cpu' => 0, + 'disk' => 10240, + ], $availability['nodes'][0]['reserved']); + } + public function test_unchanged_resource_vector_is_not_an_upgrade(): void { $fixture = $this->fixture(); @@ -341,6 +545,10 @@ public function test_paid_upgrade_commit_returns_explicit_handled_proof(): void $upgrade, $invoice->due_at ); + DB::table('invoices')->where('id', $invoice->id)->update([ + 'status' => Invoice::STATUS_PAID, + ]); + $invoice->refresh(); $this->assertTrue( $fixture->upgrades->commitPaidUpgrade($upgrade, $invoice) @@ -428,6 +636,10 @@ public function test_paid_upgrade_payload_is_verified_before_leasing(): void $upgrade, $invoice->due_at ); + DB::table('invoices')->where('id', $invoice->id)->update([ + 'status' => Invoice::STATUS_PAID, + ]); + $invoice->refresh(); $fixture->upgrades->commitPaidUpgrade($upgrade, $invoice); $payload = (array) $reservation->fresh()->configuration_payload; @@ -494,6 +706,151 @@ public function test_tampered_upgrade_payload_is_rejected_before_payment(): void $this->assertSame('cancelled', $reservation->fresh()->status); } + public function test_live_target_config_drift_is_rejected_before_payment(): void + { + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + DB::table('service_configs') + ->where('configurable_type', ServiceUpgrade::class) + ->where('configurable_id', $upgrade->id) + ->where( + 'config_option_id', + $fixture->options['memory']->id + ) + ->update(['slider_value' => 16384]); + + $failure = $fixture->upgrades->preflightPaidUpgrade( + $upgrade, + $invoice + ); + + $this->assertStringContainsString( + 'immutable integrity', + strtolower((string) $failure) + ); + $this->assertSame( + ServiceUpgrade::STATUS_CANCELLED, + $upgrade->fresh()->status + ); + $this->assertSame('cancelled', $reservation->fresh()->status); + } + + public function test_hidden_slider_cannot_detach_existing_capacity_commitment(): void + { + Queue::fake(); + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + DB::table('config_options') + ->whereIn('id', collect($fixture->options)->pluck('id')) + ->update(['hidden' => true]); + DB::table('invoices')->where('id', $invoice->id)->update([ + 'status' => Invoice::STATUS_PAID, + ]); + $invoice->refresh(); + + $this->assertTrue( + $fixture->upgrades->commitPaidUpgrade($upgrade, $invoice) + ); + $this->assertSame( + 'paid_committed', + $reservation->fresh()->status + ); + $this->assertSame( + ServiceUpgrade::STATUS_PAID_COMMITTED, + $upgrade->fresh()->status + ); + } + + public function test_server_extension_drift_is_rejected_before_payment(): void + { + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + DB::table('extensions') + ->where('id', $fixture->server->id) + ->update(['extension' => 'DifferentServer']); + + $failure = $fixture->upgrades->preflightPaidUpgrade( + $upgrade, + $invoice + ); + + $this->assertStringContainsString( + 'immutable integrity', + strtolower((string) $failure) + ); + $this->assertSame( + ServiceUpgrade::STATUS_CANCELLED, + $upgrade->fresh()->status + ); + $this->assertSame('cancelled', $reservation->fresh()->status); + } + + public function test_completion_rechecks_live_target_inside_core_transaction(): void + { + Queue::fake(); + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + DB::table('invoices')->where('id', $invoice->id)->update([ + 'status' => Invoice::STATUS_PAID, + ]); + $invoice->refresh(); + $fixture->upgrades->commitPaidUpgrade($upgrade, $invoice); + $provisioningUpgrade = app(ServiceUpgradeService::class) + ->beginProvisioning($upgrade->fresh()); + $contract = $fixture->upgrades->beginProvisioning( + $provisioningUpgrade + ); + DB::table('service_configs') + ->where('configurable_type', ServiceUpgrade::class) + ->where('configurable_id', $upgrade->id) + ->where( + 'config_option_id', + $fixture->options['memory']->id + ) + ->update(['slider_value' => 16384]); + + try { + DB::transaction( + fn () => $fixture->upgrades->completeProvisioning( + $provisioningUpgrade, + $contract['provisioning_lease_id'] + ) + ); + $this->fail( + 'Expected completion-time target drift to fail closed.' + ); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'immutable integrity', + strtolower($exception->getMessage()) + ); + } + + $this->assertSame( + 'paid_committed', + $reservation->fresh()->status + ); + $this->assertNotNull( + $reservation->fresh()->provisioning_lease_id + ); + } + public function test_tampered_invoice_line_is_cancelled_before_paid_transition(): void { $fixture = $this->fixture(); @@ -1057,6 +1414,7 @@ private function fixture(): object 'selectChild' => $selectChild, 'selectAlternate' => $selectAlternate, 'remote' => $remote, + 'inventory' => $inventory, 'upgrades' => $upgrades, 'checkoutReservationId' => $checkoutReservationId, 'checkoutInvoice' => $checkoutInvoice, From 977761187f523adc34182856d7542005a748f9e3 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 11:56:38 +1000 Subject: [PATCH 44/95] fix: complete extension stock integrity manifest --- Models/ResourceReservation.php | 8 +- .../UpgradeReservationIntegrityService.php | 1002 +++++++++++++++++ ...dentity_to_ptero_resource_reservations.php | 8 +- 3 files changed, 1011 insertions(+), 7 deletions(-) create mode 100644 Services/UpgradeReservationIntegrityService.php diff --git a/Models/ResourceReservation.php b/Models/ResourceReservation.php index 6a7ca45..1bc8d82 100644 --- a/Models/ResourceReservation.php +++ b/Models/ResourceReservation.php @@ -127,10 +127,10 @@ public function scopePending($query) public function scopeHoldingCapacity($query) { return $query->where(function ($query) { - $query->where(function ($query) { - $query->where('status', self::STATUS_PENDING) - ->where('expires_at', '>', now()); - })->orWhere('status', self::STATUS_PAID_COMMITTED); + $query->where( + 'status', + self::STATUS_PENDING + )->orWhere('status', self::STATUS_PAID_COMMITTED); }); } diff --git a/Services/UpgradeReservationIntegrityService.php b/Services/UpgradeReservationIntegrityService.php new file mode 100644 index 0000000..9a84f88 --- /dev/null +++ b/Services/UpgradeReservationIntegrityService.php @@ -0,0 +1,1002 @@ + $context + */ + public function fingerprint(object $upgrade, array $context): string + { + return hash('sha256', json_encode( + $this->canonicalizeSnapshot([ + 'upgrade_id' => (int) $upgrade->id, + 'source_fingerprint' => + (string) $upgrade->source_fingerprint, + 'target_fingerprint' => + (string) $upgrade->target_fingerprint, + 'panel_identity' => $context['panel_identity'], + 'node_id' => $context['node_id'], + 'location_id' => $context['location_id'], + 'external_server_id' => + $context['external_server_id'], + 'external_server_uuid' => + $context['external_server_uuid'], + 'external_server_identifier' => + $context['external_server_identifier'], + 'external_server_external_id' => + $context['external_server_external_id'], + 'external_user_id' => $context['external_user_id'], + 'user_external_id' => $context['user_external_id'], + 'user_email' => $context['user_email'], + 'nest_id' => $context['nest_id'], + 'egg_id' => $context['egg_id'], + 'preserved_build' => $context['preserved_build'], + 'allocation_id' => $context['allocation_id'], + 'assigned_allocation_ids' => + $context['assigned_allocation_ids'], + 'source' => $context['source'], + 'target' => $context['target'], + 'delta' => $context['delta'], + 'quoted_amount' => $this->normalizedMoney( + $upgrade->quoted_amount + ), + 'currency_code' => + strtoupper((string) $upgrade->currency_code), + ]), + JSON_THROW_ON_ERROR + | JSON_PRESERVE_ZERO_FRACTION + | JSON_UNESCAPED_SLASHES + )); + } + + public function pricingVersion(object $upgrade): string + { + return hash('sha256', json_encode([ + 'quoted_amount' => $this->normalizedMoney( + $upgrade->quoted_amount + ), + 'currency_code' => + strtoupper((string) $upgrade->currency_code), + ], JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES)); + } + + /** + * @return array + */ + public function verifiedSnapshot( + object $upgrade, + object $reservation + ): array { + $payload = $reservation->configuration_payload; + if (is_string($payload)) { + try { + $payload = json_decode( + $payload, + true, + 512, + JSON_THROW_ON_ERROR + ); + } catch (\JsonException $exception) { + throw new InvalidStockConfigurationException( + 'The upgrade capacity snapshot is unreadable.', + previous: $exception + ); + } + } + if (! is_array($payload)) { + throw new InvalidStockConfigurationException( + 'The upgrade capacity snapshot is unreadable.' + ); + } + + try { + $fingerprint = $this->fingerprint($upgrade, $payload); + $pricingVersion = $this->pricingVersion($upgrade); + $quotedAmount = $this->normalizedMoney( + $upgrade->quoted_amount ?? null + ); + $reservedAmount = $this->normalizedMoney( + $reservation->calculated_price ?? null + ); + } catch (\Throwable $exception) { + throw new InvalidStockConfigurationException( + 'The upgrade capacity snapshot failed its immutable integrity check.', + previous: $exception + ); + } + + if ($upgrade instanceof ServiceUpgrade) { + $this->assertLiveTargetMatches($upgrade); + } + + $source = $this->resourceVector($payload['source'] ?? null); + $target = $this->resourceVector($payload['target'] ?? null); + $delta = $this->resourceVector($payload['delta'] ?? null); + $rowTarget = $this->resourceVector([ + 'memory' => $reservation->memory ?? null, + 'cpu' => $reservation->cpu ?? null, + 'disk' => $reservation->disk ?? null, + ]); + $rowDelta = $this->resourceVector([ + 'memory' => $reservation->reserved_memory ?? null, + 'cpu' => $reservation->reserved_cpu ?? null, + 'disk' => $reservation->reserved_disk ?? null, + ]); + $upgradeId = $this->positiveInteger($upgrade->id ?? null); + $upgradeServiceId = $this->positiveInteger( + $upgrade->service_id ?? null + ); + $reservationServiceId = $this->positiveInteger( + $reservation->service_id ?? null + ); + $reservationUpgradeId = $this->positiveInteger( + $reservation->service_upgrade_id ?? null + ); + $payloadUpgradeId = $this->positiveInteger( + $payload['service_upgrade_id'] ?? null + ); + $nodeId = $this->positiveInteger($reservation->node_id ?? null); + $payloadNodeId = $this->positiveInteger( + $payload['node_id'] ?? null + ); + $locationId = $this->positiveInteger( + $reservation->location_id ?? null + ); + $payloadLocationId = $this->positiveInteger( + $payload['location_id'] ?? null + ); + $externalServerId = $this->positiveInteger( + $reservation->external_server_id ?? null + ); + $payloadExternalServerId = $this->positiveInteger( + $payload['external_server_id'] ?? null + ); + $externalUserId = $this->positiveInteger( + $reservation->external_user_id ?? null + ); + $payloadExternalUserId = $this->positiveInteger( + $payload['external_user_id'] ?? null + ); + $nestId = $this->positiveInteger($payload['nest_id'] ?? null); + $eggId = $this->positiveInteger($payload['egg_id'] ?? null); + $allocationId = $this->positiveInteger( + $payload['allocation_id'] ?? null + ); + $assignedAllocationIds = $this->positiveIntegerList( + $payload['assigned_allocation_ids'] ?? null + ); + $preservedBuild = $this->preservedBuild( + $payload['preserved_build'] ?? null + ); + $panelIdentity = $payload['panel_identity'] ?? null; + $externalServerUuid = $payload['external_server_uuid'] ?? null; + $externalServerIdentifier = + $payload['external_server_identifier'] ?? null; + $externalServerExternalId = + $payload['external_server_external_id'] ?? null; + $userExternalId = $payload['user_external_id'] ?? null; + $userEmail = $payload['user_email'] ?? null; + $sourceSnapshot = $this->decodedArray( + $upgrade->source_snapshot ?? null + ); + $targetSnapshot = $this->decodedArray( + $upgrade->target_snapshot ?? null + ); + $sourceProperties = $this->snapshotProperties($sourceSnapshot); + $targetProperties = $this->snapshotProperties($targetSnapshot); + $sourceSnapshotHash = $this->snapshotFingerprint( + $sourceSnapshot + ); + $targetSnapshotHash = $this->snapshotFingerprint( + $targetSnapshot + ); + $snapshotSource = $this->resourceVectorFromProperties( + $sourceProperties + ); + $snapshotTarget = $this->resourceVectorFromProperties( + $targetProperties + ); + $snapshotLocation = $this->locationFromProperties( + $targetProperties + ); + $targetRecurring = StrictDecimal::parseNonNegative( + $targetSnapshot['recurring_price'] ?? null + ); + $sourceFingerprint = $upgrade->source_fingerprint ?? null; + $targetFingerprint = $upgrade->target_fingerprint ?? null; + $service = $upgrade->service ?? null; + $product = $upgrade->product ?? null; + $serviceUserId = $this->positiveInteger( + $upgrade->service_user_id + ?? ($service?->user_id ?? null) + ); + $serviceProductId = $this->positiveInteger( + $upgrade->service_product_id + ?? ($service?->product_id ?? null) + ); + $servicePlanId = $this->positiveInteger( + $upgrade->service_plan_id + ?? ($service?->plan_id ?? null) + ); + $serviceQuantity = StrictInteger::parse( + $upgrade->service_quantity + ?? ($service?->quantity ?? null) + ); + $serviceCurrency = strtoupper((string) ( + $upgrade->service_currency_code + ?? ($service?->currency_code ?? '') + )); + $upgradeProductId = $this->positiveInteger( + $upgrade->product_id ?? null + ); + $upgradePlanId = $this->positiveInteger( + $upgrade->plan_id ?? null + ); + $upgradeInvoiceId = $this->positiveInteger( + $upgrade->invoice_id ?? null + ); + $invoice = $upgrade->invoice ?? null; + $invoiceStatus = (string) ( + $upgrade->invoice_status + ?? ($invoice?->status ?? '') + ); + $invoiceUserId = $this->positiveInteger( + $upgrade->invoice_user_id + ?? ($invoice?->user_id ?? null) + ); + $invoiceCurrency = strtoupper((string) ( + $upgrade->invoice_currency_code + ?? ($invoice?->currency_code ?? '') + )); + $productServerId = $this->positiveInteger( + $upgrade->product_server_id + ?? ($product?->server_id ?? null) + ); + $reservationUserId = $this->positiveInteger( + $reservation->user_id ?? null + ); + $reservationProductId = $this->positiveInteger( + $reservation->product_id ?? null + ); + $reservationPlanId = $this->positiveInteger( + $reservation->plan_id ?? null + ); + $reservationInvoiceId = $this->positiveInteger( + $reservation->invoice_id ?? null + ); + $reservationServerId = $this->positiveInteger( + $reservation->server_extension_id ?? null + ); + $reservationQuantity = StrictInteger::parse( + $reservation->quantity ?? null + ); + $upgradeCurrency = strtoupper( + (string) ($upgrade->currency_code ?? '') + ); + $reservationCurrency = strtoupper( + (string) ($reservation->currency_code ?? '') + ); + $reservationGuard = $this->positiveInteger( + $reservation->upgrade_guard_id ?? null + ); + $upgradeGuard = $this->positiveInteger( + $upgrade->active_service_guard_id ?? null + ); + $reservationStatus = (string) ( + $reservation->status ?? '' + ); + $upgradeStatus = (string) ($upgrade->status ?? ''); + if ( + $source === null + || $target === null + || $delta === null + || $rowTarget === null + || $rowDelta === null + || $sourceSnapshot === null + || $targetSnapshot === null + || $sourceProperties === null + || $targetProperties === null + || $snapshotSource === null + || $snapshotTarget === null + || $snapshotLocation === null + || $targetRecurring === null + || $sourceSnapshotHash === null + || $targetSnapshotHash === null + || ! is_string($sourceFingerprint) + || preg_match( + '/^[a-f0-9]{64}$/D', + $sourceFingerprint + ) !== 1 + || ! is_string($targetFingerprint) + || preg_match( + '/^[a-f0-9]{64}$/D', + $targetFingerprint + ) !== 1 + || ! hash_equals( + $sourceFingerprint, + $sourceSnapshotHash + ) + || ! hash_equals( + $targetFingerprint, + $targetSnapshotHash + ) + || $source !== $snapshotSource + || $target !== $snapshotTarget + || $source === $target + || collect($target)->contains( + fn (int $value): bool => $value <= 0 + ) + || $target['disk'] < $source['disk'] + || ! $this->onlyResourcesChanged( + $sourceProperties, + $targetProperties + ) + || $delta !== [ + 'memory' => max(0, $target['memory'] - $source['memory']), + 'cpu' => max(0, $target['cpu'] - $source['cpu']), + 'disk' => max(0, $target['disk'] - $source['disk']), + ] + || ($reservation->purpose ?? null) !== 'upgrade' + || $upgradeId === null + || $upgradeServiceId === null + || $reservationServiceId !== $upgradeServiceId + || $reservationUpgradeId !== $upgradeId + || $payloadUpgradeId !== $upgradeId + || $serviceUserId === null + || $reservationUserId !== $serviceUserId + || $serviceProductId === null + || $upgradeProductId !== $serviceProductId + || $reservationProductId !== $serviceProductId + || $servicePlanId === null + || $upgradePlanId !== $servicePlanId + || $reservationPlanId !== $servicePlanId + || $serviceQuantity !== 1 + || $reservationQuantity !== 1 + || $serviceCurrency === '' + || $upgradeCurrency !== $serviceCurrency + || $reservationCurrency !== $serviceCurrency + || ! $this->snapshotIdentityMatches( + $sourceSnapshot, + $targetSnapshot, + $upgradeServiceId, + $serviceProductId, + $servicePlanId, + $serviceCurrency + ) + || ( + ($upgrade->invoice_id ?? null) !== null + && $upgradeInvoiceId === null + ) + || ( + ($reservation->invoice_id ?? null) !== null + && $reservationInvoiceId === null + ) + || $reservationInvoiceId !== $upgradeInvoiceId + || ( + $this->moneyIsPositive($quotedAmount) + ? $upgradeInvoiceId === null + : $upgradeInvoiceId !== null + ) + || ! $this->invoiceLifecycleMatches( + $reservationStatus, + $this->moneyIsPositive($quotedAmount), + $upgradeInvoiceId, + $invoiceStatus, + $invoiceUserId, + $invoiceCurrency, + $serviceUserId, + $serviceCurrency + ) + || $productServerId === null + || $reservationServerId !== $productServerId + || ( + ($reservation->upgrade_guard_id ?? null) !== null + && $reservationGuard === null + ) + || ( + ($upgrade->active_service_guard_id ?? null) !== null + && $upgradeGuard === null + ) + || $quotedAmount !== $reservedAmount + || (string) ($reservation->pricing_version ?? '') + !== $pricingVersion + || (string) ($reservation->formula_version ?? '') + !== 'dynamic-upgrade-v1' + || ! $this->lifecycleMatches( + $reservationStatus, + $upgradeStatus, + $reservationGuard, + $upgradeGuard, + $upgradeId, + $upgradeServiceId, + $reservation->consumed_at ?? null + ) + || ! is_string($reservation->configuration_fingerprint) + || preg_match( + '/^[a-f0-9]{64}$/D', + $reservation->configuration_fingerprint + ) !== 1 + || ! hash_equals( + $reservation->configuration_fingerprint, + $fingerprint + ) + || (string) ($payload['source_fingerprint'] ?? '') + !== (string) $upgrade->source_fingerprint + || (string) ($payload['target_fingerprint'] ?? '') + !== (string) $upgrade->target_fingerprint + || ! is_string($panelIdentity) + || preg_match('/^[a-f0-9]{64}$/D', $panelIdentity) !== 1 + || ! is_string($reservation->panel_identity ?? null) + || ! hash_equals( + (string) $reservation->panel_identity, + $panelIdentity + ) + || $nodeId === null + || $payloadNodeId !== $nodeId + || $locationId === null + || $payloadLocationId !== $locationId + || $payloadLocationId !== $snapshotLocation + || $externalServerId === null + || $payloadExternalServerId !== $externalServerId + || $externalUserId === null + || $payloadExternalUserId !== $externalUserId + || ! is_string($externalServerUuid) + || ! Str::isUuid($externalServerUuid) + || ! is_string($reservation->external_server_uuid ?? null) + || ! hash_equals( + (string) $reservation->external_server_uuid, + $externalServerUuid + ) + || ! is_string($externalServerIdentifier) + || trim($externalServerIdentifier) === '' + || ! is_string( + $reservation->external_server_identifier ?? null + ) + || ! hash_equals( + (string) $reservation->external_server_identifier, + $externalServerIdentifier + ) + || ! is_string($externalServerExternalId) + || ! hash_equals( + (string) $upgradeServiceId, + $externalServerExternalId + ) + || ! is_string($userExternalId) + || ! hash_equals( + "paymenter-user-{$serviceUserId}", + $userExternalId + ) + || ! is_string($userEmail) + || trim($userEmail) === '' + || $nestId === null + || $eggId === null + || $allocationId === null + || $assignedAllocationIds === null + || ! in_array( + $allocationId, + $assignedAllocationIds, + true + ) + || $preservedBuild === null + || $target !== $rowTarget + || $delta !== $rowDelta + ) { + throw new InvalidStockConfigurationException( + 'The upgrade capacity snapshot failed its immutable integrity check.' + ); + } + + return $payload; + } + + /** + * The signed target snapshot is provisioning authority, while core applies + * ServiceUpgrade::configs after the remote resize. Prove those mutable rows + * still materialize the exact signed target so the two systems cannot + * diverge after quote creation. + */ + public function assertLiveTargetMatches(ServiceUpgrade $upgrade): void + { + try { + $upgrade->load([ + 'service.product.settings', + 'service.configs.configOption', + 'service.configs.configValue', + 'product.settings', + 'configs.configOption', + 'configs.configValue', + ]); + $targetSnapshot = $this->decodedArray( + $upgrade->target_snapshot + ); + $signedProperties = $this->snapshotProperties( + $targetSnapshot + ); + $liveProperties = $this->snapshotProperties([ + 'properties' => $upgrade->targetProperties(), + ]); + } catch (\Throwable $exception) { + throw new InvalidStockConfigurationException( + 'The live upgrade target cannot be reconstructed.', + previous: $exception + ); + } + + if ( + $targetSnapshot === null + || $signedProperties === null + || $liveProperties === null + || $signedProperties !== $liveProperties + || ! array_key_exists('billing_anchor', $targetSnapshot) + ) { + throw new InvalidStockConfigurationException( + 'The live upgrade target no longer matches its signed snapshot.' + ); + } + } + + /** + * @return array|null + */ + private function decodedArray(mixed $value): ?array + { + if (is_array($value)) { + return $value; + } + if (! is_string($value) || trim($value) === '') { + return null; + } + + try { + $decoded = json_decode( + $value, + true, + 512, + JSON_THROW_ON_ERROR + ); + } catch (\JsonException) { + return null; + } + + return is_array($decoded) ? $decoded : null; + } + + private function snapshotFingerprint(?array $snapshot): ?string + { + if ($snapshot === null) { + return null; + } + + try { + return hash('sha256', json_encode( + $this->canonicalizeSnapshot($snapshot), + JSON_THROW_ON_ERROR + | JSON_PRESERVE_ZERO_FRACTION + | JSON_UNESCAPED_SLASHES + )); + } catch (\JsonException) { + return null; + } + } + + /** + * ServiceUpgrade uses a distinct canonicalizer that preserves numeric + * representation. Do not reuse the checkout canonicalizer here. + * + * @param array $value + * @return array + */ + private function canonicalizeSnapshot(array $value): array + { + foreach ($value as $key => $item) { + if (is_array($item)) { + $value[$key] = $this->canonicalizeSnapshot($item); + } + } + if (! array_is_list($value)) { + ksort($value); + } + + return $value; + } + + /** + * @param array|null $snapshot + * @return array|null + */ + private function snapshotProperties(?array $snapshot): ?array + { + $properties = $snapshot['properties'] ?? null; + if (! is_array($properties) || array_is_list($properties)) { + return null; + } + + $normalized = []; + foreach ($properties as $key => $value) { + $key = strtolower((string) $key); + if ($key === '' || array_key_exists($key, $normalized)) { + return null; + } + $normalized[$key] = $value; + } + ksort($normalized); + + return $normalized; + } + + /** + * @param array|null $properties + * @return array{memory: int, cpu: int, disk: int}|null + */ + private function resourceVectorFromProperties( + ?array $properties + ): ?array { + if ($properties === null) { + return null; + } + + $vector = []; + foreach (['memory', 'cpu', 'disk'] as $resource) { + $parsed = StrictInteger::parse( + $properties[$resource] ?? null + ) ?? StrictInteger::parseStoredDecimal( + $properties[$resource] ?? null + ); + if ($parsed === null || $parsed < 0) { + return null; + } + $vector[$resource] = $parsed; + } + + return $vector; + } + + /** + * @param array|null $properties + */ + private function locationFromProperties( + ?array $properties + ): ?int { + if ($properties === null) { + return null; + } + + $location = StrictInteger::parse( + $properties['location'] ?? null + ) ?? StrictInteger::parseStoredDecimal( + $properties['location'] ?? null + ); + if ($location !== null) { + return $location > 0 ? $location : null; + } + + $locationIds = $properties['location_ids'] ?? null; + if (is_string($locationIds)) { + $decoded = json_decode($locationIds, true); + $locationIds = json_last_error() === JSON_ERROR_NONE + && is_array($decoded) + ? $decoded + : [$locationIds]; + } elseif (! is_array($locationIds)) { + $locationIds = [$locationIds]; + } + if (! array_is_list($locationIds) || count($locationIds) !== 1) { + return null; + } + + $location = StrictInteger::parse($locationIds[0]) + ?? StrictInteger::parseStoredDecimal($locationIds[0]); + + return $location !== null && $location > 0 + ? $location + : null; + } + + /** + * @param array $source + * @param array $target + */ + private function onlyResourcesChanged( + array $source, + array $target + ): bool { + $keys = array_unique(array_merge( + array_keys($source), + array_keys($target) + )); + foreach ($keys as $key) { + if (in_array($key, ['memory', 'cpu', 'disk'], true)) { + continue; + } + if ( + ! array_key_exists($key, $source) + || ! array_key_exists($key, $target) + || $source[$key] !== $target[$key] + ) { + return false; + } + } + + return true; + } + + /** + * @param array $source + * @param array $target + */ + private function snapshotIdentityMatches( + array $source, + array $target, + int $serviceId, + int $productId, + int $planId, + string $currencyCode + ): bool { + return StrictInteger::parse($source['service_id'] ?? null) + === $serviceId + && StrictInteger::parse($target['service_id'] ?? null) + === $serviceId + && StrictInteger::parse($source['product_id'] ?? null) + === $productId + && StrictInteger::parse($target['product_id'] ?? null) + === $productId + && StrictInteger::parse($source['plan_id'] ?? null) + === $planId + && StrictInteger::parse($target['plan_id'] ?? null) + === $planId + && StrictInteger::parse($source['quantity'] ?? null) === 1 + && StrictInteger::parse($target['quantity'] ?? null) === 1 + && strtoupper((string) ($source['currency_code'] ?? '')) + === $currencyCode + && strtoupper((string) ($target['currency_code'] ?? '')) + === $currencyCode + && array_key_exists('billing_anchor', $source) + && array_key_exists('billing_anchor', $target) + && $source['billing_anchor'] === $target['billing_anchor']; + } + + private function lifecycleMatches( + string $reservationStatus, + string $upgradeStatus, + ?int $reservationGuard, + ?int $upgradeGuard, + int $upgradeId, + int $serviceId, + mixed $consumedAt + ): bool { + if ($reservationStatus === 'pending') { + return in_array( + $upgradeStatus, + ['pending', 'awaiting_payment'], + true + ) + && $reservationGuard === $upgradeId + && $upgradeGuard === $serviceId + && $consumedAt === null; + } + if ($reservationStatus === 'paid_committed') { + return in_array( + $upgradeStatus, + [ + 'paid_committed', + 'provisioning', + 'retryable_failed', + 'needs_attention', + ], + true + ) + && $reservationGuard === $upgradeId + && $upgradeGuard === $serviceId + && $consumedAt === null; + } + if ($reservationStatus !== 'confirmed' || $consumedAt === null) { + return false; + } + return $upgradeStatus === 'completed' + && $reservationGuard === null + && $upgradeGuard === null; + } + + /** + * @return array{memory: int, cpu: int, disk: int}|null + */ + private function resourceVector(mixed $value): ?array + { + if (! is_array($value)) { + return null; + } + + $resources = []; + foreach (['memory', 'cpu', 'disk'] as $resource) { + $parsed = StrictInteger::parse($value[$resource] ?? null); + if ($parsed === null || $parsed < 0) { + return null; + } + $resources[$resource] = $parsed; + } + + return $resources; + } + + private function positiveInteger(mixed $value): ?int + { + $parsed = StrictInteger::parse($value); + + return $parsed !== null && $parsed > 0 ? $parsed : null; + } + + /** + * @return list|null + */ + private function positiveIntegerList(mixed $value): ?array + { + if (! is_array($value) || ! array_is_list($value)) { + return null; + } + + $normalized = []; + foreach ($value as $item) { + $parsed = $this->positiveInteger($item); + if ($parsed === null) { + return null; + } + $normalized[] = $parsed; + } + sort($normalized, SORT_NUMERIC); + + return $normalized !== [] + && count(array_unique($normalized)) === count($normalized) + ? $normalized + : null; + } + + /** + * @return array{ + * swap: int, + * io: int, + * threads: string|null, + * databases: int, + * allocations: int, + * backups: int + * }|null + */ + private function preservedBuild(mixed $value): ?array + { + if (! is_array($value)) { + return null; + } + + $threads = $value['threads'] ?? null; + $swap = StrictInteger::parse($value['swap'] ?? null); + $io = StrictInteger::parse($value['io'] ?? null); + $databases = StrictInteger::parse( + $value['databases'] ?? null + ); + $allocations = StrictInteger::parse( + $value['allocations'] ?? null + ); + $backups = StrictInteger::parse($value['backups'] ?? null); + if ( + ! array_key_exists('threads', $value) + || ($threads !== null && ! is_string($threads)) + || $swap === null + || $swap < 0 + || $io === null + || $io < 0 + || $databases === null + || $databases < 0 + || $allocations !== 0 + || $backups === null + || $backups < 0 + ) { + return null; + } + + return [ + 'swap' => $swap, + 'io' => $io, + 'threads' => $threads, + 'databases' => $databases, + 'allocations' => $allocations, + 'backups' => $backups, + ]; + } + + /** + * Database drivers do not agree on how to materialize DECIMAL(17, 2): + * the same value can arrive as "100.00", 100, or 9.9. Fingerprints must + * use one exact representation without accepting precision beyond cents. + */ + private function normalizedMoney(mixed $value): string + { + if (is_int($value)) { + $text = (string) $value; + } elseif (is_float($value) && is_finite($value)) { + $text = number_format($value, 2, '.', ''); + } elseif (is_string($value)) { + $text = $value; + } else { + throw new InvalidStockConfigurationException( + 'The upgrade quote amount is invalid.' + ); + } + + if ( + preg_match( + '/^(-?)(0|[1-9]\d*)(?:\.(\d+))?$/D', + $text, + $matches + ) !== 1 + ) { + throw new InvalidStockConfigurationException( + 'The upgrade quote amount is invalid.' + ); + } + + $fraction = $matches[3] ?? ''; + if ( + strlen($fraction) > 2 + && trim(substr($fraction, 2), '0') !== '' + ) { + throw new InvalidStockConfigurationException( + 'The upgrade quote amount exceeds cent precision.' + ); + } + + $fraction = str_pad(substr($fraction, 0, 2), 2, '0'); + $sign = ($matches[1] ?? '') === '-' + && ($matches[2] !== '0' || $fraction !== '00') + ? '-' + : ''; + + return $sign.$matches[2].'.'.$fraction; + } + + private function moneyIsPositive(string $amount): bool + { + return $amount[0] !== '-' + && $amount !== '0.00'; + } + + private function invoiceLifecycleMatches( + string $reservationStatus, + bool $positiveQuote, + ?int $invoiceId, + string $invoiceStatus, + ?int $invoiceUserId, + string $invoiceCurrency, + ?int $serviceUserId, + string $serviceCurrency + ): bool { + if (! $positiveQuote) { + return $invoiceId === null; + } + if ( + $invoiceId === null + || $invoiceUserId === null + || $serviceUserId === null + || $invoiceUserId !== $serviceUserId + || $invoiceCurrency !== $serviceCurrency + ) { + return false; + } + + return $reservationStatus === 'pending' + ? in_array($invoiceStatus, ['pending', 'paid'], true) + : $invoiceStatus === 'paid'; + } +} diff --git a/database/migrations/2026_07_25_000001_add_checkout_identity_to_ptero_resource_reservations.php b/database/migrations/2026_07_25_000001_add_checkout_identity_to_ptero_resource_reservations.php index e8fb02f..02ec52e 100644 --- a/database/migrations/2026_07_25_000001_add_checkout_identity_to_ptero_resource_reservations.php +++ b/database/migrations/2026_07_25_000001_add_checkout_identity_to_ptero_resource_reservations.php @@ -36,11 +36,13 @@ public function up(): void ->after('cart_item_guard_id'); }); - // Every pre-migration pending row came from one of the two superseded - // token flows and lacks the immutable identity needed for safe use. - // Active carts will acquire a fresh hold on edit or checkout. + // Unbound pre-migration holds came from superseded token flows and lack + // immutable identity. A service-bound row may already back an invoice; + // never retire that commitment before the readiness gate can stop the + // upgrade and require explicit operator reconciliation. DB::table('ptero_resource_reservations') ->where('status', 'pending') + ->whereNull('service_id') ->whereNull('configuration_fingerprint') ->update([ 'status' => 'cancelled', From 005a98e1e57c7b1ad913938eb2652297c6f833a3 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 12:05:32 +1000 Subject: [PATCH 45/95] fix: close cross-repository lifecycle gaps --- .../UpgradeReservationIntegrityService.php | 8 +- tests/Unit/ReservationServiceTest.php | 92 +++++++++++++++++-- tests/Unit/ResourceCalculationServiceTest.php | 9 +- 3 files changed, 101 insertions(+), 8 deletions(-) diff --git a/Services/UpgradeReservationIntegrityService.php b/Services/UpgradeReservationIntegrityService.php index 9a84f88..1b5dc20 100644 --- a/Services/UpgradeReservationIntegrityService.php +++ b/Services/UpgradeReservationIntegrityService.php @@ -995,8 +995,14 @@ private function invoiceLifecycleMatches( return false; } + // The paid-invoice transition and the capacity commitment transition + // share one database transaction. A committed read can therefore see + // either the entirely unpaid pair or the entirely paid pair, never a + // paid invoice attached to a still-pending reservation. Treat that + // split state as lifecycle drift instead of masking a failed payment + // handoff and continuing to quote stock. return $reservationStatus === 'pending' - ? in_array($invoiceStatus, ['pending', 'paid'], true) + ? $invoiceStatus === 'pending' : $invoiceStatus === 'paid'; } } diff --git a/tests/Unit/ReservationServiceTest.php b/tests/Unit/ReservationServiceTest.php index 0e55022..3cd4137 100644 --- a/tests/Unit/ReservationServiceTest.php +++ b/tests/Unit/ReservationServiceTest.php @@ -2,6 +2,7 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; +use App\Exceptions\PermanentProvisioningException; use App\Jobs\Server\CreateJob; use App\Jobs\Server\SuspendJob; use App\Helpers\ExtensionHelper; @@ -2067,14 +2068,31 @@ public function test_paid_renewal_can_reactivate_confirmed_dynamic_service(): vo { Queue::fake(); $service = $this->makeBillableService(Service::STATUS_SUSPENDED); - $this->insertReservation( - serviceId: $service->id, - userId: $service->user_id, - status: 'confirmed' - ); + DB::table('services')->where('id', $service->id)->update([ + 'price' => '10.00', + ]); + $service = $service->fresh(); + $this->insertConfirmedCheckoutCommitment($service); + $renewalInvoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PENDING, + 'currency_code' => $service->currency_code, + 'due_at' => $service->expires_at, + ]); + $renewalInvoice->items()->create([ + 'reference_type' => Service::class, + 'reference_id' => $service->id, + 'price' => $service->price, + 'quantity' => $service->quantity, + 'description' => 'Dynamic service renewal', + ]); - app(RenewServiceService::class)->handle($service); + app(MarkInvoicePaidService::class)->handle($renewalInvoice); + $this->assertSame( + Invoice::STATUS_PAID, + $renewalInvoice->fresh()->status + ); $this->assertSame(Service::STATUS_ACTIVE, $service->fresh()->status); } @@ -2564,6 +2582,68 @@ private function insertAllocation(int $reservationId, int $allocationId = 7001): ]); } + private function insertConfirmedCheckoutCommitment( + Service $service + ): int { + $checkoutInvoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PAID, + 'currency_code' => $service->currency_code, + 'due_at' => now()->subMonth(), + ]); + $checkoutInvoice->items()->create([ + 'reference_type' => Service::class, + 'reference_id' => $service->id, + 'price' => $service->price, + 'quantity' => $service->quantity, + 'description' => 'Original dynamic checkout', + ]); + + $reservationId = $this->insertReservation( + serviceId: $service->id, + invoiceId: $checkoutInvoice->id, + userId: $service->user_id, + status: ResourceReservation::STATUS_CONFIRMED, + consumedAt: now()->subMonth(), + productId: $service->product_id, + planId: $service->plan_id + ); + $serverExtensionId = (int) Product::query() + ->whereKey($service->product_id) + ->value('server_id'); + $payload = json_decode( + (string) DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('configuration_payload'), + true, + 512, + JSON_THROW_ON_ERROR + ); + $payload['server_extension_id'] = $serverExtensionId; + + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'server_extension_id' => $serverExtensionId, + 'configuration_payload' => json_encode( + $payload, + JSON_THROW_ON_ERROR + ), + 'configuration_fingerprint' => + $this->configurationService->fingerprint($payload), + 'paid_committed_at' => now()->subMonth(), + 'external_server_id' => 71, + 'external_user_id' => 44, + 'external_server_uuid' => + '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', + 'external_server_identifier' => 'created', + 'updated_at' => now(), + ]); + $this->insertAllocation($reservationId); + + return $reservationId; + } + /** * @return array */ diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index bf9886a..1ffb614 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -899,7 +899,14 @@ public function test_expired_pending_commitment_stays_counted_until_atomic_clean 'pending', ['memory' => 1024, 'cpu' => 100, 'disk' => 10240], expiresAt: now()->subMinute(), - purpose: 'checkout' + purpose: 'checkout', + allocation: [ + 'allocation_id' => 501, + 'ip' => '192.0.2.5', + 'port' => 25565, + 'environment_key' => 'SERVER_PORT', + 'is_primary' => true, + ] ); $node = $this->service()->getLocationAvailability(1)['nodes'][0]; From 5f36e606827745834dcf592afd880b11173af1bb Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 12:14:50 +1000 Subject: [PATCH 46/95] fix: scope paid upgrade transition proof --- .../UpgradeReservationIntegrityService.php | 70 ++++++++++++++++--- Services/UpgradeReservationService.php | 30 +++++--- tests/Unit/ReservationServiceTest.php | 12 +++- tests/Unit/UpgradeReservationServiceTest.php | 34 +++++++++ 4 files changed, 124 insertions(+), 22 deletions(-) diff --git a/Services/UpgradeReservationIntegrityService.php b/Services/UpgradeReservationIntegrityService.php index 1b5dc20..1d3f077 100644 --- a/Services/UpgradeReservationIntegrityService.php +++ b/Services/UpgradeReservationIntegrityService.php @@ -2,6 +2,7 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Services; +use App\Models\Invoice; use App\Models\ServiceUpgrade; use App\Support\StrictDecimal; use App\Support\StrictInteger; @@ -80,6 +81,50 @@ public function pricingVersion(object $upgrade): string public function verifiedSnapshot( object $upgrade, object $reservation + ): array { + return $this->verifySnapshot($upgrade, $reservation, null); + } + + /** + * Verify the one transient lifecycle pair that exists while the locked + * paid-invoice transaction atomically commits its capacity reservation. + * + * @return array + */ + public function verifiedSnapshotForPaidCommit( + object $upgrade, + object $reservation, + Invoice $paidInvoice + ): array { + $invoiceId = StrictInteger::parse($paidInvoice->id ?? null); + if ( + $invoiceId === null + || $invoiceId <= 0 + || $paidInvoice->status !== Invoice::STATUS_PAID + || StrictInteger::parse($upgrade->invoice_id ?? null) + !== $invoiceId + || StrictInteger::parse($reservation->invoice_id ?? null) + !== $invoiceId + ) { + throw new InvalidStockConfigurationException( + 'The paid upgrade invoice failed its atomic transition proof.' + ); + } + + return $this->verifySnapshot( + $upgrade, + $reservation, + $invoiceId + ); + } + + /** + * @return array + */ + private function verifySnapshot( + object $upgrade, + object $reservation, + ?int $atomicPaidInvoiceId ): array { $payload = $reservation->configuration_payload; if (is_string($payload)) { @@ -399,7 +444,8 @@ public function verifiedSnapshot( $invoiceUserId, $invoiceCurrency, $serviceUserId, - $serviceCurrency + $serviceCurrency, + $atomicPaidInvoiceId ) || $productServerId === null || $reservationServerId !== $productServerId @@ -980,7 +1026,8 @@ private function invoiceLifecycleMatches( ?int $invoiceUserId, string $invoiceCurrency, ?int $serviceUserId, - string $serviceCurrency + string $serviceCurrency, + ?int $atomicPaidInvoiceId ): bool { if (! $positiveQuote) { return $invoiceId === null; @@ -995,14 +1042,15 @@ private function invoiceLifecycleMatches( return false; } - // The paid-invoice transition and the capacity commitment transition - // share one database transaction. A committed read can therefore see - // either the entirely unpaid pair or the entirely paid pair, never a - // paid invoice attached to a still-pending reservation. Treat that - // split state as lifecycle drift instead of masking a failed payment - // handoff and continuing to quote stock. - return $reservationStatus === 'pending' - ? $invoiceStatus === 'pending' - : $invoiceStatus === 'paid'; + if ($reservationStatus === 'pending') { + return $invoiceStatus === 'pending' + || ( + $invoiceStatus === 'paid' + && $atomicPaidInvoiceId !== null + && $invoiceId === $atomicPaidInvoiceId + ); + } + + return $invoiceStatus === 'paid'; } } diff --git a/Services/UpgradeReservationService.php b/Services/UpgradeReservationService.php index a0e27ae..25a1641 100644 --- a/Services/UpgradeReservationService.php +++ b/Services/UpgradeReservationService.php @@ -256,14 +256,6 @@ public function commitPaidUpgrade( 'The upgrade capacity guarantee has expired.' ); } - if ( - ($integrityFailure = $this->reservationIntegrityError( - $lockedUpgrade, - $reservation - )) !== null - ) { - throw new PermanentProvisioningException($integrityFailure); - } if ( $lockedInvoice !== null && $lockedUpgrade->invoice_id !== null @@ -301,6 +293,15 @@ public function commitPaidUpgrade( throw new \RuntimeException($invoiceMismatch); } } + if ( + ($integrityFailure = $this->reservationIntegrityError( + $lockedUpgrade, + $reservation, + ! $alreadyPaid ? $lockedInvoice : null + )) !== null + ) { + throw new PermanentProvisioningException($integrityFailure); + } if (! $alreadyPaid) { $reservation->forceFill([ @@ -1400,7 +1401,8 @@ private function reservationFingerprint( private function reservationIntegrityError( ServiceUpgrade $upgrade, - UpgradeReservation $reservation + UpgradeReservation $reservation, + ?Invoice $paidCommitInvoice = null ): ?string { try { $upgrade->load([ @@ -1414,7 +1416,15 @@ private function reservationIntegrityError( 'configs.configValue', ]); $this->assertProductPanel($upgrade->service); - $this->integrity->verifiedSnapshot($upgrade, $reservation); + if ($paidCommitInvoice !== null) { + $this->integrity->verifiedSnapshotForPaidCommit( + $upgrade, + $reservation, + $paidCommitInvoice + ); + } else { + $this->integrity->verifiedSnapshot($upgrade, $reservation); + } } catch (\Throwable) { return 'The paid upgrade reservation failed its immutable integrity check.'; } diff --git a/tests/Unit/ReservationServiceTest.php b/tests/Unit/ReservationServiceTest.php index 3cd4137..9391a21 100644 --- a/tests/Unit/ReservationServiceTest.php +++ b/tests/Unit/ReservationServiceTest.php @@ -2,6 +2,7 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; +use App\Enums\InvoiceTransactionStatus; use App\Exceptions\PermanentProvisioningException; use App\Jobs\Server\CreateJob; use App\Jobs\Server\SuspendJob; @@ -2087,8 +2088,17 @@ public function test_paid_renewal_can_reactivate_confirmed_dynamic_service(): vo 'description' => 'Dynamic service renewal', ]); - app(MarkInvoicePaidService::class)->handle($renewalInvoice); + $payment = ExtensionHelper::addPayment( + $renewalInvoice, + null, + $service->price, + transactionId: 'paid-renewal-reactivation' + ); + $this->assertSame( + InvoiceTransactionStatus::Succeeded, + $payment->fresh()->status + ); $this->assertSame( Invoice::STATUS_PAID, $renewalInvoice->fresh()->status diff --git a/tests/Unit/UpgradeReservationServiceTest.php b/tests/Unit/UpgradeReservationServiceTest.php index 47567c2..42f6036 100644 --- a/tests/Unit/UpgradeReservationServiceTest.php +++ b/tests/Unit/UpgradeReservationServiceTest.php @@ -563,6 +563,40 @@ public function test_paid_upgrade_commit_returns_explicit_handled_proof(): void ); } + public function test_paid_commit_transition_does_not_bypass_invoice_line_proof(): void + { + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + DB::table('invoice_items') + ->where('id', $invoice->items()->firstOrFail()->id) + ->update(['price' => 1]); + DB::table('invoices')->where('id', $invoice->id)->update([ + 'status' => Invoice::STATUS_PAID, + ]); + + try { + $fixture->upgrades->commitPaidUpgrade( + $upgrade, + $invoice->fresh() + ); + $this->fail( + 'Expected the paid commit to reject a tampered invoice line.' + ); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'invoice line', + strtolower($exception->getMessage()) + ); + } + + $this->assertSame('pending', $reservation->fresh()->status); + $this->assertNull($reservation->fresh()->paid_committed_at); + } + public function test_dynamic_upgrade_rejects_non_resource_configuration_change(): void { $fixture = $this->fixture(); From 59fd806faf70ea9b5ebb90f045708ad576825e79 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Sun, 26 Jul 2026 12:25:47 +1000 Subject: [PATCH 47/95] fix: normalize durable readiness proofs --- migration-readiness.php | 28 +++++++++++++ .../LegacyReservationReadinessTest.php | 42 +++++++++++++++++++ tests/Unit/ReservationServiceTest.php | 24 ++++++++++- 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/migration-readiness.php b/migration-readiness.php index 7441e62..7efd83b 100644 --- a/migration-readiness.php +++ b/migration-readiness.php @@ -1521,6 +1521,34 @@ private function currentServiceProperties(Service $service): ?array ), ExtensionHelper::getServiceProperties($service) ); + // MariaDB hydrates DECIMAL slider values as strings while SQLite + // commonly returns integers. Restore their exact stored integer + // representation before comparing the live service with its + // signed target. Do not apply today's mutable min/max/step rules + // to a historical upgrade that has already completed. + foreach ($service->configs as $config) { + $option = $config->configOption; + if ( + $option === null + || ! $option->isDynamicSlider() + || $config->slider_value === null + ) { + continue; + } + $key = strtolower((string) ( + $option->env_variable ?: $option->name + )); + if (! in_array($key, ['memory', 'cpu', 'disk'], true)) { + continue; + } + $numericValue = StrictInteger::parseStoredDecimal( + $config->slider_value + ); + if ($numericValue === null) { + return null; + } + $properties[$key] = $numericValue; + } } catch (\Throwable) { return null; } diff --git a/tests/Feature/LegacyReservationReadinessTest.php b/tests/Feature/LegacyReservationReadinessTest.php index 01a5e3e..8694415 100644 --- a/tests/Feature/LegacyReservationReadinessTest.php +++ b/tests/Feature/LegacyReservationReadinessTest.php @@ -891,6 +891,48 @@ public function test_completed_upgrade_with_applied_target_passes_readiness(): v $this->addToAssertionCount(1); } + public function test_completed_upgrade_remains_ready_after_slider_policy_changes(): void + { + $reservationId = $this->insertCompleteUpgradeReservation(); + $this->completeUpgrade($reservationId, applyTarget: true); + $serviceId = DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('service_id'); + $this->assertNotNull($serviceId); + $optionId = DB::table('service_configs') + ->join( + 'config_options', + 'config_options.id', + '=', + 'service_configs.config_option_id' + ) + ->where('service_configs.configurable_type', Service::class) + ->where('service_configs.configurable_id', $serviceId) + ->where('config_options.env_variable', 'memory') + ->value('config_options.id'); + $this->assertNotNull($optionId); + $option = ConfigOption::query()->findOrFail((int) $optionId); + $metadata = (array) $option->metadata; + $metadata['min'] = 9000; + $metadata['step'] = 2048; + $metadata['default'] = 9000; + $option->metadata = $metadata; + $option->save(); + + try { + $option->fresh()->normalizeDynamicSliderValue(8192); + $this->fail( + 'Expected the historical target to violate the new slider policy.' + ); + } catch (\InvalidArgumentException) { + $this->addToAssertionCount(1); + } + + (new LegacyReservationReadinessService)->assertReady(); + + $this->addToAssertionCount(1); + } + public function test_upgrade_source_and_target_billing_anchors_must_match(): void { $reservationId = $this->insertCompleteUpgradeReservation(); diff --git a/tests/Unit/ReservationServiceTest.php b/tests/Unit/ReservationServiceTest.php index 9391a21..3d6dfe3 100644 --- a/tests/Unit/ReservationServiceTest.php +++ b/tests/Unit/ReservationServiceTest.php @@ -2099,9 +2099,23 @@ public function test_paid_renewal_can_reactivate_confirmed_dynamic_service(): vo InvoiceTransactionStatus::Succeeded, $payment->fresh()->status ); + $this->assertSame( + number_format( + (float) $renewalInvoice->fresh()->total, + 2, + '.', + '' + ), + number_format((float) $payment->fresh()->amount, 2, '.', '') + ); + $paidInvoice = $renewalInvoice->fresh(); + $this->assertNull( + $paidInvoice->payment_attention_required_at, + (string) $paidInvoice->payment_attention_reason + ); $this->assertSame( Invoice::STATUS_PAID, - $renewalInvoice->fresh()->status + $paidInvoice->status ); $this->assertSame(Service::STATUS_ACTIVE, $service->fresh()->status); } @@ -2630,11 +2644,19 @@ private function insertConfirmedCheckoutCommitment( JSON_THROW_ON_ERROR ); $payload['server_extension_id'] = $serverExtensionId; + $checkoutPrice = number_format( + (float) $service->price, + 2, + '.', + '' + ); + $payload['calculated_price'] = $checkoutPrice; DB::table('ptero_resource_reservations') ->where('id', $reservationId) ->update([ 'server_extension_id' => $serverExtensionId, + 'calculated_price' => $checkoutPrice, 'configuration_payload' => json_encode( $payload, JSON_THROW_ON_ERROR From c4e5525577301e527760f4adeb54092e54953eb0 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 27 Jul 2026 20:34:59 +1000 Subject: [PATCH 48/95] fix: close dynamic stock release blockers --- .../cross-repository-integration.yml | 63 +- Admin/Pages/SetupWizard.php | 690 ++++++++-------- Admin/Resources/AlertConfigResource.php | 21 +- .../Resources/NodeCapacityPolicyResource.php | 3 +- Admin/Resources/ReservationResource.php | 42 +- DynamicPterodactyl.php | 76 +- .../InvalidResourceSelectionException.php | 4 +- .../InvalidStockConfigurationException.php | 4 +- Exceptions/StockUnavailableException.php | 4 +- .../Api/Admin/AdminReservationController.php | 10 +- .../Api/ResourceQuoteController.php | 4 +- .../Api/UpgradeQuoteController.php | 3 +- Models/NodeCapacityPolicy.php | 6 +- Models/ResourceReservation.php | 4 +- Models/SchedulerHeartbeat.php | 46 ++ .../PaymentAttentionNotification.php | 8 +- .../ProvisioningFailedNotification.php | 16 +- .../SchedulerTaskFailureNotification.php | 57 ++ Services/AlertService.php | 179 +++- Services/AllocationSelectionService.php | 12 +- Services/AuditLogService.php | 2 +- Services/ConfigOptionSetupService.php | 8 +- .../ProductResourceConfigurationService.php | 6 +- .../QuoteRateLimitConfigurationService.php | 4 +- Services/QuoteRateLimiterService.php | 3 +- Services/ReservationConfigurationService.php | 14 +- Services/ReservationService.php | 771 ++++++++++-------- Services/ResourceCalculationService.php | 94 +-- Services/ResourceQuoteService.php | 3 +- Services/SchedulerHealthService.php | 520 ++++++++++++ Services/SchedulerOperatorAlertService.php | 85 ++ .../UpgradeReservationIntegrityService.php | 28 +- Services/UpgradeReservationService.php | 354 ++++---- ...5_000002_normalize_dynamic_option_keys.php | 290 ++++++- ...able_fulfillment_to_ptero_reservations.php | 12 +- ..._07_26_000003_add_cpu_alert_thresholds.php | 10 +- ...6_07_26_000005_widen_reservation_price.php | 2 +- ...ce_one_checkout_commitment_per_service.php | 5 +- ...ict_durable_reservation_parent_deletes.php | 87 ++ ...0050_create_scheduler_heartbeats_table.php | 79 ++ ...7_26_000060_allow_system_audit_entries.php | 43 + ...dd_scan_cursor_to_scheduler_heartbeats.php | 28 + migration-readiness.php | 78 +- resources/views/admin/dashboard.blade.php | 10 +- routes/api.php | 4 +- tests/Feature/AlertConfigResourceTest.php | 42 + tests/Feature/AlertScheduleTest.php | 96 ++- tests/Feature/AuditLogServiceTest.php | 100 +++ tests/Feature/AvailabilityApiTest.php | 2 +- .../DurableReservationForeignKeyTest.php | 135 +++ .../LegacyReservationReadinessTest.php | 92 +-- ...ormalizeDynamicOptionKeysMigrationTest.php | 327 ++++++++ tests/Feature/ReservationStatisticsTest.php | 76 ++ tests/Feature/SetupWizardValidationTest.php | 2 +- tests/Unit/AlertServiceTest.php | 64 +- tests/Unit/AllocationSelectionServiceTest.php | 12 +- tests/Unit/CartItemCreatedListenerTest.php | 106 +++ tests/Unit/ConfigOptionSetupServiceTest.php | 4 +- tests/Unit/NodeSelectionServiceTest.php | 3 +- ...roductResourceConfigurationServiceTest.php | 9 +- .../Unit/PterodactylInventoryServiceTest.php | 3 +- tests/Unit/QuoteRateLimiterServiceTest.php | 2 +- .../ReservationConfigurationServiceTest.php | 3 +- tests/Unit/ReservationServiceTest.php | 307 ++++++- tests/Unit/ResourceCalculationServiceTest.php | 111 ++- tests/Unit/ResourceQuoteServiceTest.php | 14 +- tests/Unit/SchedulerHealthServiceTest.php | 512 ++++++++++++ tests/Unit/UpgradeReservationServiceTest.php | 78 +- 68 files changed, 4523 insertions(+), 1369 deletions(-) create mode 100644 Models/SchedulerHeartbeat.php create mode 100644 Notifications/SchedulerTaskFailureNotification.php create mode 100644 Services/SchedulerHealthService.php create mode 100644 Services/SchedulerOperatorAlertService.php create mode 100644 database/migrations/2026_07_26_000040_restrict_durable_reservation_parent_deletes.php create mode 100644 database/migrations/2026_07_26_000050_create_scheduler_heartbeats_table.php create mode 100644 database/migrations/2026_07_26_000060_allow_system_audit_entries.php create mode 100644 database/migrations/2026_07_26_000070_add_scan_cursor_to_scheduler_heartbeats.php create mode 100644 tests/Feature/AlertConfigResourceTest.php create mode 100644 tests/Feature/AuditLogServiceTest.php create mode 100644 tests/Feature/DurableReservationForeignKeyTest.php create mode 100644 tests/Feature/NormalizeDynamicOptionKeysMigrationTest.php create mode 100644 tests/Feature/ReservationStatisticsTest.php create mode 100644 tests/Unit/CartItemCreatedListenerTest.php create mode 100644 tests/Unit/SchedulerHealthServiceTest.php diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml index 008df84..19d2650 100644 --- a/.github/workflows/cross-repository-integration.yml +++ b/.github/workflows/cross-repository-integration.yml @@ -15,6 +15,57 @@ concurrency: cancel-in-progress: true jobs: + quality: + name: Extension quality + runs-on: ubuntu-latest + + steps: + - name: Check out Dynamic Pterodactyl + uses: actions/checkout@v7 + with: + path: dynamic-pterodactyl + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha || github.sha }} + + - name: Check out companion Paymenter + uses: actions/checkout@v7 + with: + repository: ObsidianNetwork/Paymenter-Obsidian-Network + ref: 5bcb23966d0801ec5059e205511c24af0f9a3276 + path: paymenter + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + extensions: bcmath, curl, gd, mbstring, mysql, openssl, pdo, tokenizer, xml, zip + tools: composer:v2 + coverage: none + + - name: Install Paymenter dependencies + working-directory: paymenter + run: composer install --no-interaction --no-ansi --prefer-dist --no-progress + + - name: Audit Composer dependencies + working-directory: paymenter + run: composer audit --locked --no-interaction + + - name: Run Pint on the complete extension branch diff + working-directory: dynamic-pterodactyl + env: + BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }} + run: | + if [[ -z "$BASE_SHA" || "$BASE_SHA" =~ ^0+$ ]]; then + BASE_SHA="$(git rev-parse HEAD^)" + fi + mapfile -d '' files < <( + git diff --diff-filter=ACMR --name-only -z \ + "$BASE_SHA"...HEAD -- '*.php' + ) + if ((${#files[@]})); then + ../paymenter/vendor/bin/pint --test "${files[@]}" + fi + extension-sqlite: name: PHP ${{ matrix.php }} / SQLite runs-on: ubuntu-latest @@ -27,15 +78,15 @@ jobs: steps: - name: Check out Dynamic Pterodactyl - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: path: dynamic-pterodactyl - name: Check out companion Paymenter - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: codex/paymenter-1.5.6-remediation + ref: 5bcb23966d0801ec5059e205511c24af0f9a3276 path: paymenter - name: Set up PHP @@ -123,15 +174,15 @@ jobs: steps: - name: Check out Dynamic Pterodactyl - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: path: dynamic-pterodactyl - name: Check out companion Paymenter - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: codex/paymenter-1.5.6-remediation + ref: 5bcb23966d0801ec5059e205511c24af0f9a3276 path: paymenter - name: Set up PHP diff --git a/Admin/Pages/SetupWizard.php b/Admin/Pages/SetupWizard.php index 2c47c28..f8ba77d 100644 --- a/Admin/Pages/SetupWizard.php +++ b/Admin/Pages/SetupWizard.php @@ -82,382 +82,382 @@ public function form(Schema $schema): Schema return $schema ->components([ Form::make([ - Tabs::make('Wizard')->tabs([ - - // TAB 1: Product Selection - Tabs\Tab::make('Product') - ->icon('heroicon-o-cube') - ->schema([ - Select::make('product_id') - ->label('Select Product') - ->options(fn () => Product::query() - ->where('hidden', false) - ->whereHas('server', fn ($query) => $query - ->where('extension', 'Pterodactyl') - ->where('enabled', true)) - ->pluck('name', 'id')) - ->required() - ->searchable() - ->live() - ->afterStateUpdated(function (Get $get, Set $set, ?int $state) { - if ($state) { - $this->checkExistingOptions($state); - } else { - $this->existingOptions = null; - $this->showOverwriteWarning = false; - } - }), - - Placeholder::make('existing_warning') - ->label('') - ->content(fn () => $this->showOverwriteWarning - ? '⚠️ This product already has ' . ($this->existingOptions['existing_count'] ?? 0) . ' dynamic slider config option(s). Running the wizard will update them.' - : '') - ->visible(fn () => $this->showOverwriteWarning), - - Section::make('Pricing Model') - ->schema([ - Select::make('pricing_model') - ->options([ - 'linear' => 'Linear (per-unit pricing)', - 'tiered' => 'Tiered (volume discounts)', - 'base_addon' => 'Base + Addon', - ]) - ->default('linear') - ->live() - ->required(), - - TextInput::make('base_price') - ->label('Base Price') - ->prefix('$') - ->numeric() - ->required() - ->minValue(0) - ->default(0) - ->helperText('Monthly base price before resource costs'), - ]), - ]), - - // TAB 2: Resource Sliders - Tabs\Tab::make('Sliders') - ->icon('heroicon-o-adjustments-horizontal') - ->schema([ - // Memory Slider - Section::make('Memory Slider') - ->schema([ - Toggle::make('enable_memory_slider') - ->label('Enable Memory Slider') - ->default(true) - ->live(), - Grid::make(4) - ->visible(fn (Get $get) => $get('enable_memory_slider')) - ->schema([ - TextInput::make('memory_min') - ->label('Min') - ->suffix('GB') + Tabs::make('Wizard')->tabs([ + + // TAB 1: Product Selection + Tabs\Tab::make('Product') + ->icon('heroicon-o-cube') + ->schema([ + Select::make('product_id') + ->label('Select Product') + ->options(fn () => Product::query() + ->where('hidden', false) + ->whereHas('server', fn ($query) => $query + ->where('extension', 'Pterodactyl') + ->where('enabled', true)) + ->pluck('name', 'id')) + ->required() + ->searchable() + ->live() + ->afterStateUpdated(function (Get $get, Set $set, ?int $state) { + if ($state) { + $this->checkExistingOptions($state); + } else { + $this->existingOptions = null; + $this->showOverwriteWarning = false; + } + }), + + Placeholder::make('existing_warning') + ->label('') + ->content(fn () => $this->showOverwriteWarning + ? '⚠️ This product already has '.($this->existingOptions['existing_count'] ?? 0).' dynamic slider config option(s). Running the wizard will update them.' + : '') + ->visible(fn () => $this->showOverwriteWarning), + + Section::make('Pricing Model') + ->schema([ + Select::make('pricing_model') + ->options([ + 'linear' => 'Linear (per-unit pricing)', + 'tiered' => 'Tiered (volume discounts)', + 'base_addon' => 'Base + Addon', + ]) + ->default('linear') + ->live() + ->required(), + + TextInput::make('base_price') + ->label('Base Price') + ->prefix('$') + ->numeric() + ->required() + ->minValue(0) + ->default(0) + ->helperText('Monthly base price before resource costs'), + ]), + ]), + + // TAB 2: Resource Sliders + Tabs\Tab::make('Sliders') + ->icon('heroicon-o-adjustments-horizontal') + ->schema([ + // Memory Slider + Section::make('Memory Slider') + ->schema([ + Toggle::make('enable_memory_slider') + ->label('Enable Memory Slider') + ->default(true) + ->live(), + Grid::make(4) + ->visible(fn (Get $get) => $get('enable_memory_slider')) + ->schema([ + TextInput::make('memory_min') + ->label('Min') + ->suffix('GB') + ->numeric() + ->required() + ->minValue(0.0001) + ->default(1), + TextInput::make('memory_max') + ->label('Max') + ->suffix('GB') + ->numeric() + ->required() + ->minValue(0.0001) + ->default(64), + TextInput::make('memory_step') + ->label('Step') + ->suffix('GB') + ->numeric() + ->required() + ->minValue(0.0001) + ->default(1), + TextInput::make('memory_default') + ->label('Default') + ->suffix('GB') + ->numeric() + ->required() + ->minValue(0.0001) + ->default(4), + ]), + ]), + + // CPU Slider + Section::make('CPU Slider') + ->schema([ + Toggle::make('enable_cpu_slider') + ->label('Enable CPU Slider') + ->default(true) + ->live(), + Grid::make(4) + ->visible(fn (Get $get) => $get('enable_cpu_slider')) + ->schema([ + TextInput::make('cpu_min') + ->label('Min') + ->suffix('cores') + ->numeric() + ->required() + ->minValue(0.0001) + ->default(1), + TextInput::make('cpu_max') + ->label('Max') + ->suffix('cores') + ->numeric() + ->required() + ->minValue(0.0001) + ->default(8), + TextInput::make('cpu_step') + ->label('Step') + ->numeric() + ->required() + ->minValue(0.0001) + ->default(1), + TextInput::make('cpu_default') + ->label('Default') + ->suffix('cores') + ->numeric() + ->required() + ->minValue(0.0001) + ->default(2), + ]), + ]), + + // Disk Slider + Section::make('Disk Slider') + ->schema([ + Toggle::make('enable_disk_slider') + ->label('Enable Disk Slider') + ->default(true) + ->live(), + Grid::make(4) + ->visible(fn (Get $get) => $get('enable_disk_slider')) + ->schema([ + TextInput::make('disk_min') + ->label('Min') + ->suffix('GB') + ->numeric() + ->required() + ->minValue(0.0001) + ->default(10), + TextInput::make('disk_max') + ->label('Max') + ->suffix('GB') + ->numeric() + ->required() + ->minValue(0.0001) + ->default(500), + TextInput::make('disk_step') + ->label('Step') + ->suffix('GB') + ->numeric() + ->required() + ->minValue(0.0001) + ->default(10), + TextInput::make('disk_default') + ->label('Default') + ->suffix('GB') + ->numeric() + ->required() + ->minValue(0.0001) + ->default(50), + ]), + ]), + ]), + + // TAB 3: Pricing Details + Tabs\Tab::make('Pricing') + ->icon('heroicon-o-currency-dollar') + ->schema([ + // LINEAR pricing + Section::make('Linear Rates') + ->description('Set price per unit for each resource type') + ->visible(fn (Get $get) => $get('pricing_model') === 'linear') + ->schema([ + Grid::make(3)->schema([ + TextInput::make('memory_rate') + ->label('Memory Rate') + ->prefix('$') + ->suffix('/GB/mo') ->numeric() ->required() - ->minValue(0.0001) - ->default(1), - TextInput::make('memory_max') - ->label('Max') - ->suffix('GB') + ->minValue(0) + ->default(0.50), + TextInput::make('cpu_rate') + ->label('CPU Rate') + ->prefix('$') + ->suffix('/core/mo') ->numeric() ->required() - ->minValue(0.0001) - ->default(64), - TextInput::make('memory_step') - ->label('Step') - ->suffix('GB') + ->minValue(0) + ->default(2.00), + TextInput::make('disk_rate') + ->label('Disk Rate') + ->prefix('$') + ->suffix('/GB/mo') ->numeric() ->required() - ->minValue(0.0001) - ->default(1), - TextInput::make('memory_default') - ->label('Default') + ->minValue(0) + ->default(0.02), + ]), + ]), + + // TIERED pricing + Section::make('Memory Tiers') + ->description('Volume discounts - price decreases as quantity increases') + ->visible(fn (Get $get) => $get('pricing_model') === 'tiered') + ->schema([ + Repeater::make('memory_tiers') + ->schema([ + TextInput::make('up_to') + ->label('Up to (GB)') + ->numeric() + ->minValue(0) + ->placeholder('∞ (leave empty for unlimited)'), + TextInput::make('rate') + ->label('Price per GB') + ->prefix('$') + ->numeric() + ->minValue(0) + ->required(), + ]) + ->columns(2) + ->addActionLabel('Add Tier') + ->defaultItems(2) + ->default([ + ['up_to' => 8, 'rate' => 0.75], + ['up_to' => null, 'rate' => 0.50], + ]), + ]), + + Section::make('CPU Tiers') + ->visible(fn (Get $get) => $get('pricing_model') === 'tiered') + ->schema([ + Repeater::make('cpu_tiers') + ->schema([ + TextInput::make('up_to') + ->label('Up to (cores)') + ->numeric() + ->minValue(0) + ->placeholder('∞'), + TextInput::make('rate') + ->label('Price per core') + ->prefix('$') + ->numeric() + ->minValue(0) + ->required(), + ]) + ->columns(2) + ->addActionLabel('Add Tier') + ->defaultItems(1) + ->default([ + ['up_to' => null, 'rate' => 2.00], + ]), + ]), + + Section::make('Disk Tiers') + ->visible(fn (Get $get) => $get('pricing_model') === 'tiered') + ->schema([ + Repeater::make('disk_tiers') + ->schema([ + TextInput::make('up_to') + ->label('Up to (GB)') + ->numeric() + ->minValue(0) + ->placeholder('∞'), + TextInput::make('rate') + ->label('Price per GB') + ->prefix('$') + ->numeric() + ->minValue(0) + ->required(), + ]) + ->columns(2) + ->addActionLabel('Add Tier') + ->defaultItems(1) + ->default([ + ['up_to' => null, 'rate' => 0.02], + ]), + ]), + + // BASE + ADDON pricing + Section::make('Included Resources') + ->description('Resources included in base price') + ->visible(fn (Get $get) => $get('pricing_model') === 'base_addon') + ->schema([ + Grid::make(3)->schema([ + TextInput::make('memory_included') + ->label('Included Memory') ->suffix('GB') ->numeric() ->required() - ->minValue(0.0001) + ->minValue(0) ->default(4), - ]), - ]), - - // CPU Slider - Section::make('CPU Slider') - ->schema([ - Toggle::make('enable_cpu_slider') - ->label('Enable CPU Slider') - ->default(true) - ->live(), - Grid::make(4) - ->visible(fn (Get $get) => $get('enable_cpu_slider')) - ->schema([ - TextInput::make('cpu_min') - ->label('Min') - ->suffix('cores') - ->numeric() - ->required() - ->minValue(0.0001) - ->default(1), - TextInput::make('cpu_max') - ->label('Max') - ->suffix('cores') - ->numeric() - ->required() - ->minValue(0.0001) - ->default(8), - TextInput::make('cpu_step') - ->label('Step') - ->numeric() - ->required() - ->minValue(0.0001) - ->default(1), - TextInput::make('cpu_default') - ->label('Default') + TextInput::make('cpu_included') + ->label('Included CPU') ->suffix('cores') ->numeric() ->required() - ->minValue(0.0001) + ->minValue(0) ->default(2), - ]), - ]), - - // Disk Slider - Section::make('Disk Slider') - ->schema([ - Toggle::make('enable_disk_slider') - ->label('Enable Disk Slider') - ->default(true) - ->live(), - Grid::make(4) - ->visible(fn (Get $get) => $get('enable_disk_slider')) - ->schema([ - TextInput::make('disk_min') - ->label('Min') - ->suffix('GB') - ->numeric() - ->required() - ->minValue(0.0001) - ->default(10), - TextInput::make('disk_max') - ->label('Max') - ->suffix('GB') - ->numeric() - ->required() - ->minValue(0.0001) - ->default(500), - TextInput::make('disk_step') - ->label('Step') + TextInput::make('disk_included') + ->label('Included Disk') ->suffix('GB') ->numeric() ->required() - ->minValue(0.0001) - ->default(10), - TextInput::make('disk_default') - ->label('Default') - ->suffix('GB') - ->numeric() - ->required() - ->minValue(0.0001) + ->minValue(0) ->default(50), ]), - ]), - ]), - - // TAB 3: Pricing Details - Tabs\Tab::make('Pricing') - ->icon('heroicon-o-currency-dollar') - ->schema([ - // LINEAR pricing - Section::make('Linear Rates') - ->description('Set price per unit for each resource type') - ->visible(fn (Get $get) => $get('pricing_model') === 'linear') - ->schema([ - Grid::make(3)->schema([ - TextInput::make('memory_rate') - ->label('Memory Rate') - ->prefix('$') - ->suffix('/GB/mo') - ->numeric() - ->required() - ->minValue(0) - ->default(0.50), - TextInput::make('cpu_rate') - ->label('CPU Rate') - ->prefix('$') - ->suffix('/core/mo') - ->numeric() - ->required() - ->minValue(0) - ->default(2.00), - TextInput::make('disk_rate') - ->label('Disk Rate') - ->prefix('$') - ->suffix('/GB/mo') - ->numeric() - ->required() - ->minValue(0) - ->default(0.02), ]), - ]), - - // TIERED pricing - Section::make('Memory Tiers') - ->description('Volume discounts - price decreases as quantity increases') - ->visible(fn (Get $get) => $get('pricing_model') === 'tiered') - ->schema([ - Repeater::make('memory_tiers') - ->schema([ - TextInput::make('up_to') - ->label('Up to (GB)') - ->numeric() - ->minValue(0) - ->placeholder('∞ (leave empty for unlimited)'), - TextInput::make('rate') - ->label('Price per GB') + + Section::make('Overage Rates') + ->description('Price for resources beyond included amount') + ->visible(fn (Get $get) => $get('pricing_model') === 'base_addon') + ->schema([ + Grid::make(3)->schema([ + TextInput::make('memory_overage') + ->label('Memory Overage') ->prefix('$') + ->suffix('/GB/mo') ->numeric() + ->required() ->minValue(0) - ->required(), - ]) - ->columns(2) - ->addActionLabel('Add Tier') - ->defaultItems(2) - ->default([ - ['up_to' => 8, 'rate' => 0.75], - ['up_to' => null, 'rate' => 0.50], - ]), - ]), - - Section::make('CPU Tiers') - ->visible(fn (Get $get) => $get('pricing_model') === 'tiered') - ->schema([ - Repeater::make('cpu_tiers') - ->schema([ - TextInput::make('up_to') - ->label('Up to (cores)') - ->numeric() - ->minValue(0) - ->placeholder('∞'), - TextInput::make('rate') - ->label('Price per core') + ->default(0.75), + TextInput::make('cpu_overage') + ->label('CPU Overage') ->prefix('$') + ->suffix('/core/mo') ->numeric() + ->required() ->minValue(0) - ->required(), - ]) - ->columns(2) - ->addActionLabel('Add Tier') - ->defaultItems(1) - ->default([ - ['up_to' => null, 'rate' => 2.00], - ]), - ]), - - Section::make('Disk Tiers') - ->visible(fn (Get $get) => $get('pricing_model') === 'tiered') - ->schema([ - Repeater::make('disk_tiers') - ->schema([ - TextInput::make('up_to') - ->label('Up to (GB)') - ->numeric() - ->minValue(0) - ->placeholder('∞'), - TextInput::make('rate') - ->label('Price per GB') + ->default(3.00), + TextInput::make('disk_overage') + ->label('Disk Overage') ->prefix('$') + ->suffix('/GB/mo') ->numeric() + ->required() ->minValue(0) - ->required(), - ]) - ->columns(2) - ->addActionLabel('Add Tier') - ->defaultItems(1) - ->default([ - ['up_to' => null, 'rate' => 0.02], + ->default(0.05), ]), - ]), - - // BASE + ADDON pricing - Section::make('Included Resources') - ->description('Resources included in base price') - ->visible(fn (Get $get) => $get('pricing_model') === 'base_addon') - ->schema([ - Grid::make(3)->schema([ - TextInput::make('memory_included') - ->label('Included Memory') - ->suffix('GB') - ->numeric() - ->required() - ->minValue(0) - ->default(4), - TextInput::make('cpu_included') - ->label('Included CPU') - ->suffix('cores') - ->numeric() - ->required() - ->minValue(0) - ->default(2), - TextInput::make('disk_included') - ->label('Included Disk') - ->suffix('GB') - ->numeric() - ->required() - ->minValue(0) - ->default(50), ]), - ]), - - Section::make('Overage Rates') - ->description('Price for resources beyond included amount') - ->visible(fn (Get $get) => $get('pricing_model') === 'base_addon') - ->schema([ - Grid::make(3)->schema([ - TextInput::make('memory_overage') - ->label('Memory Overage') - ->prefix('$') - ->suffix('/GB/mo') - ->numeric() - ->required() - ->minValue(0) - ->default(0.75), - TextInput::make('cpu_overage') - ->label('CPU Overage') - ->prefix('$') - ->suffix('/core/mo') - ->numeric() - ->required() - ->minValue(0) - ->default(3.00), - TextInput::make('disk_overage') - ->label('Disk Overage') - ->prefix('$') - ->suffix('/GB/mo') - ->numeric() - ->required() - ->minValue(0) - ->default(0.05), + ]), + + // TAB 4: Locations + Tabs\Tab::make('Locations') + ->icon('heroicon-o-map-pin') + ->schema([ + Section::make('Location Selection') + ->description('Select which Pterodactyl locations to enable for this product') + ->schema([ + Select::make('locations') + ->label('Allowed Locations') + ->multiple() + ->options(fn () => $this->getLocationOptions()) + ->helperText('Select one or more customer choices, or leave empty only when the product has exactly one valid static Pterodactyl location.'), ]), - ]), - ]), - - // TAB 4: Locations - Tabs\Tab::make('Locations') - ->icon('heroicon-o-map-pin') - ->schema([ - Section::make('Location Selection') - ->description('Select which Pterodactyl locations to enable for this product') - ->schema([ - Select::make('locations') - ->label('Allowed Locations') - ->multiple() - ->options(fn () => $this->getLocationOptions()) - ->helperText('Select one or more customer choices, or leave empty only when the product has exactly one valid static Pterodactyl location.'), - ]), - ]), - ])->columnSpanFull(), + ]), + ])->columnSpanFull(), ]), ]) ->statePath('data'); @@ -571,7 +571,7 @@ protected function getLocationOptions(): array $locations = app(ResourceCalculationService::class)->getLocations(); return collect($locations)->mapWithKeys(fn ($loc) => [ - $loc['id'] => ($loc['long'] ?: $loc['short']) . ' (ID: ' . $loc['id'] . ')', + $loc['id'] => ($loc['long'] ?: $loc['short']).' (ID: '.$loc['id'].')', ])->toArray(); } catch (\Exception $e) { return []; diff --git a/Admin/Resources/AlertConfigResource.php b/Admin/Resources/AlertConfigResource.php index 361eeb4..6335b7a 100644 --- a/Admin/Resources/AlertConfigResource.php +++ b/Admin/Resources/AlertConfigResource.php @@ -2,18 +2,18 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Admin\Resources; +use Filament\Actions\Action as TableAction; use Filament\Actions\DeleteBulkAction; use Filament\Actions\EditAction; -use Filament\Schemas\Components\Grid; -use Filament\Schemas\Components\Section; use Filament\Forms\Components\Select; use Filament\Forms\Components\TagsInput; use Filament\Forms\Components\TextInput; use Filament\Forms\Components\Toggle; use Filament\Resources\Resource; +use Filament\Schemas\Components\Grid; +use Filament\Schemas\Components\Section; use Filament\Schemas\Components\Utilities\Get; use Filament\Schemas\Schema; -use Filament\Actions\Action as TableAction; use Filament\Tables\Columns\IconColumn; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; @@ -43,10 +43,7 @@ public static function form(Schema $schema): Schema return $schema->components([ Select::make('location_id') ->label('Location') - ->options(fn () => array_merge( - ['' => 'Global (All Locations)'], - self::getLocationOptions() - )) + ->options(fn () => self::getScopedLocationOptions()) ->placeholder('Global (All Locations)'), Toggle::make('is_active') @@ -203,6 +200,16 @@ private static function getLocationOptions(): array } } + /** + * Array union preserves numeric Pterodactyl location IDs. array_merge() + * would silently reindex them from zero and save the wrong location. + */ + private static function getScopedLocationOptions(): array + { + return ['' => 'Global (All Locations)'] + + self::getLocationOptions(); + } + private static function getLocationName(int $locationId): string { $locations = self::getLocationOptions(); diff --git a/Admin/Resources/NodeCapacityPolicyResource.php b/Admin/Resources/NodeCapacityPolicyResource.php index ce87803..e9cf216 100644 --- a/Admin/Resources/NodeCapacityPolicyResource.php +++ b/Admin/Resources/NodeCapacityPolicyResource.php @@ -98,8 +98,7 @@ public static function table(Table $table): Table TextColumn::make('effective_cpu') ->label('Effective CPU') ->getStateUsing( - fn (NodeCapacityPolicy $record): string => - number_format($record->effectiveCpuCapacity()).'%' + fn (NodeCapacityPolicy $record): string => number_format($record->effectiveCpuCapacity()).'%' ), IconColumn::make('enabled')->boolean(), ]) diff --git a/Admin/Resources/ReservationResource.php b/Admin/Resources/ReservationResource.php index 6370af8..413795b 100644 --- a/Admin/Resources/ReservationResource.php +++ b/Admin/Resources/ReservationResource.php @@ -60,7 +60,15 @@ public static function table(Table $table): Table )), TextColumn::make('calculated_price') ->label('Price') - ->money('usd'), + ->formatStateUsing( + fn ( + mixed $state, + ResourceReservation $record + ): string => self::formatPrice( + $state, + $record->currency_code + ) + ), TextColumn::make('expires_at') ->label('Expires') ->dateTime() @@ -92,7 +100,10 @@ public static function table(Table $table): Table ->form([ TextInput::make('minutes') ->label('Minutes to add') - ->numeric() + ->integer() + ->minValue(1) + ->maxValue(60) + ->step(1) ->default(15) ->required(), ]) @@ -126,6 +137,33 @@ public static function table(Table $table): Table ->poll('30s'); } + private static function formatPrice( + mixed $state, + mixed $currencyCode + ): string { + $amount = is_int($state) + ? (string) $state + : (is_string($state) ? $state : ''); + if ( + preg_match( + '/^(0|[1-9]\d*)(?:\.(\d{1,2}))?$/D', + $amount, + $matches + ) !== 1 + ) { + return 'Price unavailable'; + } + $amount = $matches[1] + .'.' + .str_pad($matches[2] ?? '', 2, '0'); + $currency = strtoupper(trim((string) $currencyCode)); + if (preg_match('/^[A-Z]{3}$/D', $currency) !== 1) { + return "{$amount} (currency unavailable)"; + } + + return "{$currency} {$amount}"; + } + public static function getPages(): array { return [ diff --git a/DynamicPterodactyl.php b/DynamicPterodactyl.php index fba1d1a..7d0713f 100644 --- a/DynamicPterodactyl.php +++ b/DynamicPterodactyl.php @@ -14,12 +14,15 @@ use Illuminate\Support\Facades\View; use Paymenter\Extensions\Others\DynamicPterodactyl\Listeners\CartItemCreatedListener; use Paymenter\Extensions\Others\DynamicPterodactyl\Listeners\CartItemDeletedListener; +use Paymenter\Extensions\Others\DynamicPterodactyl\Models\AlertConfig; +use Paymenter\Extensions\Others\DynamicPterodactyl\Models\Observers\AlertConfigObserver; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\ResourceReservation; use Paymenter\Extensions\Others\DynamicPterodactyl\Policies\ResourceReservationPolicy; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AlertService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\LegacyReservationReadinessService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\QuoteRateLimiterService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\SchedulerHealthService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\UpgradeReservationService; #[ExtensionMeta( @@ -146,45 +149,84 @@ public function boot(): void app(QuoteRateLimiterService::class)->register(); // Register routes - require __DIR__ . '/routes/api.php'; + require __DIR__.'/routes/api.php'; // Register views (for admin pages if any) - View::addNamespace('dynamic-pterodactyl', __DIR__ . '/resources/views'); + View::addNamespace('dynamic-pterodactyl', __DIR__.'/resources/views'); // Register event listeners for cart and checkout flow (reservations) $this->registerEventListeners(); - \Paymenter\Extensions\Others\DynamicPterodactyl\Models\AlertConfig::observe( - \Paymenter\Extensions\Others\DynamicPterodactyl\Models\Observers\AlertConfigObserver::class + AlertConfig::observe( + AlertConfigObserver::class ); // Note: Frontend sliders now handled by native Paymenter dynamic_slider config option type // The extension now only manages resource reservations and availability checks - // Scheduled cleanup: transition expired pending reservations. - // Keeps admin dashboards accurate and preserves the TTL guarantee on confirm(). - Schedule::call(function (): void { - app(UpgradeReservationService::class)->expireUnpaidUpgrades(); - app(ReservationService::class)->cleanupExpired(); - }) + // Each lifecycle type owns an independent scheduler event and overlap + // lock. A failure in one task cannot suppress another task type. + Schedule::call( + fn () => app(SchedulerHealthService::class)->run( + SchedulerHealthService::TASK_EXPIRE_CHECKOUT, + fn () => app(ReservationService::class)->cleanupExpired() + ) + ) + ->everyMinute() + ->name('dynamic-pterodactyl:expire-checkout-reservations') + ->withoutOverlapping(5); + + Schedule::call( + fn () => app(SchedulerHealthService::class)->run( + SchedulerHealthService::TASK_EXPIRE_UPGRADES, + fn () => app(UpgradeReservationService::class) + ->expireUnpaidUpgrades() + ) + ) ->everyMinute() - ->name('dynamic-pterodactyl:cleanup-expired-reservations') + ->name('dynamic-pterodactyl:expire-upgrade-reservations') ->withoutOverlapping(5); Schedule::call( - function (): void { - app(ReservationService::class)->reconcileStalledPaidCommitments(); - app(UpgradeReservationService::class)->reconcileStalledUpgrades(); - } + fn () => app(SchedulerHealthService::class)->run( + SchedulerHealthService::TASK_RECONCILE_CHECKOUT, + fn () => app(ReservationService::class) + ->reconcileStalledPaidCommitments() + ) ) ->everyTenMinutes() - ->name('dynamic-pterodactyl:reconcile-paid-commitments') + ->name( + 'dynamic-pterodactyl:reconcile-paid-checkout-commitments' + ) ->withoutOverlapping(15); - Schedule::call(fn () => app(AlertService::class)->checkCapacityAlerts()) + Schedule::call( + fn () => app(SchedulerHealthService::class)->run( + SchedulerHealthService::TASK_RECONCILE_UPGRADES, + fn () => app(UpgradeReservationService::class) + ->reconcileStalledUpgrades() + ) + ) + ->everyTenMinutes() + ->name('dynamic-pterodactyl:reconcile-paid-upgrades') + ->withoutOverlapping(15); + + Schedule::call( + fn () => app(SchedulerHealthService::class)->run( + SchedulerHealthService::TASK_CAPACITY_ALERTS, + fn () => app(AlertService::class)->checkCapacityAlerts() + ) + ) ->everyFiveMinutes() ->name('dynamic-pterodactyl:check-capacity-alerts') ->withoutOverlapping(10); + + Schedule::call( + fn () => app(SchedulerHealthService::class)->checkForLag() + ) + ->everyFiveMinutes() + ->name('dynamic-pterodactyl:monitor-scheduler-health') + ->withoutOverlapping(10); } /** diff --git a/Exceptions/InvalidResourceSelectionException.php b/Exceptions/InvalidResourceSelectionException.php index 9a6a3e0..9005394 100644 --- a/Exceptions/InvalidResourceSelectionException.php +++ b/Exceptions/InvalidResourceSelectionException.php @@ -2,6 +2,4 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions; -class InvalidResourceSelectionException extends \InvalidArgumentException -{ -} +class InvalidResourceSelectionException extends \InvalidArgumentException {} diff --git a/Exceptions/InvalidStockConfigurationException.php b/Exceptions/InvalidStockConfigurationException.php index c2cab30..efeb787 100644 --- a/Exceptions/InvalidStockConfigurationException.php +++ b/Exceptions/InvalidStockConfigurationException.php @@ -2,6 +2,4 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions; -class InvalidStockConfigurationException extends \RuntimeException -{ -} +class InvalidStockConfigurationException extends \RuntimeException {} diff --git a/Exceptions/StockUnavailableException.php b/Exceptions/StockUnavailableException.php index 096ed02..ca61435 100644 --- a/Exceptions/StockUnavailableException.php +++ b/Exceptions/StockUnavailableException.php @@ -2,6 +2,4 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions; -class StockUnavailableException extends \RuntimeException -{ -} +class StockUnavailableException extends \RuntimeException {} diff --git a/Http/Controllers/Api/Admin/AdminReservationController.php b/Http/Controllers/Api/Admin/AdminReservationController.php index f4adb2e..4d9a46b 100644 --- a/Http/Controllers/Api/Admin/AdminReservationController.php +++ b/Http/Controllers/Api/Admin/AdminReservationController.php @@ -18,18 +18,18 @@ public function __construct(ReservationService $reservationService) public function index(Request $request): JsonResponse { $validated = $request->validate([ - 'status' => 'nullable|string|in:pending,paid_committed,confirmed,cancelled,expired', + 'status' => 'nullable|string|in:pending,paid_committed,confirmed,cancelled,expired', 'location_id' => 'nullable|integer', - 'node_id' => 'nullable|integer', - 'user_id' => 'nullable|integer', - 'per_page' => 'nullable|integer|min:1|max:100', + 'node_id' => 'nullable|integer', + 'user_id' => 'nullable|integer', + 'per_page' => 'nullable|integer|min:1|max:100', ]); $query = $this->reservationService->queryAll($validated); return response()->json([ 'success' => true, - 'data' => $query->paginate($validated['per_page'] ?? 25), + 'data' => $query->paginate($validated['per_page'] ?? 25), ]); } diff --git a/Http/Controllers/Api/ResourceQuoteController.php b/Http/Controllers/Api/ResourceQuoteController.php index c16a5c8..98ed533 100644 --- a/Http/Controllers/Api/ResourceQuoteController.php +++ b/Http/Controllers/Api/ResourceQuoteController.php @@ -14,9 +14,7 @@ class ResourceQuoteController { - public function __construct(private readonly ResourceQuoteService $quotes) - { - } + public function __construct(private readonly ResourceQuoteService $quotes) {} public function __invoke(ResourceQuoteRequest $request, int $product): JsonResponse { diff --git a/Http/Controllers/Api/UpgradeQuoteController.php b/Http/Controllers/Api/UpgradeQuoteController.php index 16216ba..7a2007e 100644 --- a/Http/Controllers/Api/UpgradeQuoteController.php +++ b/Http/Controllers/Api/UpgradeQuoteController.php @@ -14,8 +14,7 @@ class UpgradeQuoteController { public function __construct( private readonly UpgradeReservationService $upgrades - ) { - } + ) {} public function __invoke( Request $request, diff --git a/Models/NodeCapacityPolicy.php b/Models/NodeCapacityPolicy.php index d112478..ae67590 100644 --- a/Models/NodeCapacityPolicy.php +++ b/Models/NodeCapacityPolicy.php @@ -204,10 +204,8 @@ private function lockCapacityScopes(): void ]; } $scopes = collect($scopes) - ->unique(fn (array $scope): string => - "{$scope['panel_identity']}:{$scope['location_id']}") - ->sortBy(fn (array $scope): string => - "{$scope['panel_identity']}:" + ->unique(fn (array $scope): string => "{$scope['panel_identity']}:{$scope['location_id']}") + ->sortBy(fn (array $scope): string => "{$scope['panel_identity']}:" .str_pad((string) $scope['location_id'], 10, '0', STR_PAD_LEFT)) ->values(); diff --git a/Models/ResourceReservation.php b/Models/ResourceReservation.php index 1bc8d82..df14248 100644 --- a/Models/ResourceReservation.php +++ b/Models/ResourceReservation.php @@ -121,7 +121,7 @@ public function allocations(): HasMany public function scopePending($query) { return $query->where('status', 'pending') - ->where('expires_at', '>', now()); + ->where('expires_at', '>', now()); } public function scopeHoldingCapacity($query) @@ -140,6 +140,6 @@ public function scopeHoldingCapacity($query) public function scopeExpired($query) { return $query->where('status', 'pending') - ->where('expires_at', '<=', now()); + ->where('expires_at', '<=', now()); } } diff --git a/Models/SchedulerHeartbeat.php b/Models/SchedulerHeartbeat.php new file mode 100644 index 0000000..cec666d --- /dev/null +++ b/Models/SchedulerHeartbeat.php @@ -0,0 +1,46 @@ + 'integer', + 'lag_threshold_seconds' => 'integer', + 'last_started_at' => 'datetime', + 'last_completed_at' => 'datetime', + 'last_succeeded_at' => 'datetime', + 'last_failed_at' => 'datetime', + 'last_lag_checked_at' => 'datetime', + 'lag_detected_at' => 'datetime', + 'last_alerted_at' => 'datetime', + 'last_scanned_entity_id' => 'integer', + 'last_processed_count' => 'integer', + 'last_failure_count' => 'integer', + 'consecutive_failures' => 'integer', + 'last_failure_context' => 'array', + ]; +} diff --git a/Notifications/PaymentAttentionNotification.php b/Notifications/PaymentAttentionNotification.php index fbe0d59..9d40e35 100644 --- a/Notifications/PaymentAttentionNotification.php +++ b/Notifications/PaymentAttentionNotification.php @@ -26,10 +26,10 @@ public function toMail($notifiable): MailMessage return (new MailMessage) ->subject('[Paymenter] Capacity invoice payment needs refund review') ->line('Payment activity exists after a dynamic-capacity guarantee expired.') - ->line('Invoice ID: ' . ($this->snapshot['invoice_id'] ?? 'unknown')) - ->line('Service ID: ' . ($this->snapshot['service_id'] ?? 'unknown')) - ->line('Reason: ' . ($this->snapshot['error'] ?? 'unknown')) + ->line('Invoice ID: '.($this->snapshot['invoice_id'] ?? 'unknown')) + ->line('Service ID: '.($this->snapshot['service_id'] ?? 'unknown')) + ->line('Reason: '.($this->snapshot['error'] ?? 'unknown')) ->line('Capacity was not consumed. Review the gateway transaction and issue a refund or account credit.') - ->action('View invoice', url('/admin/invoices/' . ($this->snapshot['invoice_id'] ?? 0) . '/edit')); + ->action('View invoice', url('/admin/invoices/'.($this->snapshot['invoice_id'] ?? 0).'/edit')); } } diff --git a/Notifications/ProvisioningFailedNotification.php b/Notifications/ProvisioningFailedNotification.php index 02e1b1d..c68a387 100644 --- a/Notifications/ProvisioningFailedNotification.php +++ b/Notifications/ProvisioningFailedNotification.php @@ -45,20 +45,20 @@ public function toMail($notifiable): MailMessage ->when( $upgrade, fn (MailMessage $message) => $message->line( - 'Upgrade ID: ' . ($this->snapshot['upgrade_id'] ?? 'unknown') + 'Upgrade ID: '.($this->snapshot['upgrade_id'] ?? 'unknown') ) ) - ->line('Service ID: ' . $serviceId) - ->line('Invoice ID: ' . ($this->snapshot['invoice_id'] ?? 'free service')) - ->line('Reservation ID: ' . ($this->snapshot['reservation_id'] ?? 'unknown')) - ->line('Node ID: ' . ($this->snapshot['node_id'] ?? 'unknown')) - ->line('Attempts: ' . ($this->snapshot['attempts'] ?? 0)) - ->line('Last error: ' . ($this->snapshot['error'] ?? 'unknown')) + ->line('Service ID: '.$serviceId) + ->line('Invoice ID: '.($this->snapshot['invoice_id'] ?? 'free service')) + ->line('Reservation ID: '.($this->snapshot['reservation_id'] ?? 'unknown')) + ->line('Node ID: '.($this->snapshot['node_id'] ?? 'unknown')) + ->line('Attempts: '.($this->snapshot['attempts'] ?? 0)) + ->line('Last error: '.($this->snapshot['error'] ?? 'unknown')) ->line(match (true) { $cancellation => 'The cancellation tombstone remains active. Confirm the external server is deleted before resolving it.', $upgrade => 'The paid capacity delta remains committed. Reconcile the panel state before manually resolving the upgrade.', default => 'The paid capacity remains committed and automatic reconciliation will continue.', }) - ->action('View service', url('/admin/services/' . $serviceId . '/edit')); + ->action('View service', url('/admin/services/'.$serviceId.'/edit')); } } diff --git a/Notifications/SchedulerTaskFailureNotification.php b/Notifications/SchedulerTaskFailureNotification.php new file mode 100644 index 0000000..4da7230 --- /dev/null +++ b/Notifications/SchedulerTaskFailureNotification.php @@ -0,0 +1,57 @@ + $context + */ + public function __construct(public array $context) {} + + public function via($notifiable): array + { + return ['mail']; + } + + public function toMail($notifiable): MailMessage + { + $task = (string) ($this->context['task'] ?? 'unknown'); + $lagging = ($this->context['kind'] ?? null) === 'scheduler_lag'; + + return (new MailMessage) + ->subject( + $lagging + ? '[Paymenter] Dynamic Pterodactyl scheduler is lagging' + : '[Paymenter] Dynamic Pterodactyl scheduled task failed' + ) + ->line('Task: '.$task) + ->when( + isset($this->context['entity_type']), + fn (MailMessage $message) => $message->line( + 'Record: ' + .$this->context['entity_type'] + .' #' + .($this->context['entity_id'] ?? 'unknown') + ) + ) + ->when( + isset($this->context['lag_seconds']), + fn (MailMessage $message) => $message->line( + 'Seconds since last successful run: ' + .$this->context['lag_seconds'] + ) + ) + ->line( + 'Last error: ' + .($this->context['error'] ?? 'The scheduler missed its healthy-run threshold.') + ) + ->line( + 'Inspect the scheduler heartbeat record and the application log before retrying or changing fulfillment state.' + ) + ->action('Open admin panel', url('/admin')); + } +} diff --git a/Services/AlertService.php b/Services/AlertService.php index a05fd87..7b7dda0 100644 --- a/Services/AlertService.php +++ b/Services/AlertService.php @@ -9,6 +9,7 @@ use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Notification; use Paymenter\Extensions\Others\DynamicPterodactyl\Events\AlertDeliveryFailed; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\AlertConfig; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\AlertDeliveryLog; @@ -32,48 +33,102 @@ public function __construct(ResourceCalculationService $resourceService) /** * Check all locations for capacity alerts */ - public function checkCapacityAlerts(): void + public function checkCapacityAlerts(int $chunkSize = 100): int { - $alertConfigs = DB::table('ptero_alert_configs') + $processed = 0; + $chunkSize = max(1, min($chunkSize, 500)); + $schedulerHealth = app(SchedulerHealthService::class); + + DB::table('ptero_alert_configs') ->where('is_active', true) - ->get(); + ->chunkById( + $chunkSize, + function (Collection $configs) use ( + &$processed, + $schedulerHealth + ): void { + $processed += $schedulerHealth->processRows( + SchedulerHealthService::TASK_CAPACITY_ALERTS, + 'alert_config', + $configs->pluck('id'), + function (int $alertConfigId) use ( + $schedulerHealth + ): bool { + $config = DB::table( + 'ptero_alert_configs' + ) + ->where('id', $alertConfigId) + ->where('is_active', true) + ->first(); + if ($config === null) { + return false; + } + + $this->checkAlertConfig( + $config, + $schedulerHealth + ); + + return true; + } + ); + }, + 'id' + ); - foreach ($alertConfigs as $config) { - $this->checkAlertConfig($config); - } + return $processed; } - private function checkAlertConfig(object $config): void - { + private function checkAlertConfig( + object $config, + ?SchedulerHealthService $schedulerHealth = null, + ): void { // Skip if in cooldown if ($config->last_notification_at && now()->diffInMinutes($config->last_notification_at) < $config->cooldown_minutes) { return; } - try { - if ($config->location_id) { - $locations = [$config->location_id]; - } else { - $locations = collect($this->resourceService->getLocations())->pluck('id'); - } + if ($config->location_id) { + $locations = [$config->location_id]; + } else { + $locations = collect($this->resourceService->getLocations())->pluck('id'); + } - foreach ($locations as $locationId) { - $availability = $this->resourceService->getLocationAvailability($locationId); + $schedulerHealth ??= app(SchedulerHealthService::class); + $schedulerHealth->processRows( + SchedulerHealthService::TASK_CAPACITY_ALERTS, + 'alert_config_location', + collect($locations)->map( + fn ($locationId): string => (int) $config->id + .':' + .(int) $locationId + ), + function (string $identity) use ($config): bool { + [, $locationId] = array_map( + 'intval', + explode(':', $identity, 2) + ); + $availability = $this->resourceService + ->getLocationAvailability($locationId); $alerts = $this->checkThresholds($availability, $config); - if (! empty($alerts) && $this->sendNotifications($config, $availability, $alerts)) { + if ( + ! empty($alerts) + && $this->sendNotifications( + $config, + $availability, + $alerts + ) + ) { DB::table('ptero_alert_configs') ->where('id', $config->id) ->update(['last_notification_at' => now()]); } + + return true; } - } catch (\Exception $e) { - Log::error('Alert check failed', [ - 'config_id' => $config->id, - 'error' => $e->getMessage(), - ]); - } + ); } private function checkThresholds(array $availability, object $config): array @@ -134,7 +189,7 @@ private function sendNotifications(object $config, array $availability, array $a $locationScope = $availability['location_id'] ?? $config->location_id ?? null; $locationName = $availability['location_name'] ?? $config->location_name - ?? ($locationScope !== null ? 'Location #' . $locationScope : 'All Locations'); + ?? ($locationScope !== null ? 'Location #'.$locationScope : 'All Locations'); $alertConfig = $this->hydrateAlertConfig((object) array_merge((array) $config, [ 'location_id' => $locationScope, 'location_name' => $locationName, @@ -146,14 +201,21 @@ private function sendNotifications(object $config, array $availability, array $a if ($config->email_notifications) { $channelsTried[] = 'email'; - $recipients = $this->getAdminRecipients(); + $configuredEmails = $this->configuredNotificationEmails($config); + $recipients = $this->getAdminRecipients()->reject( + fn (User $recipient): bool => in_array( + strtolower((string) $recipient->email), + $configuredEmails, + true + ) + ); - if ($recipients->isEmpty()) { - Log::warning('No admin recipients configured for capacity alert', [ + if ($recipients->isEmpty() && $configuredEmails === []) { + Log::warning('No email recipients configured for capacity alert', [ 'alert_config_id' => $config->id, ]); $channelsFailed[] = 'email'; - $lastError = 'No admin recipients configured'; + $lastError = 'No email recipients configured'; } else { $emailDelivered = false; @@ -175,6 +237,29 @@ private function sendNotifications(object $config, array $availability, array $a } } + foreach ($configuredEmails as $email) { + try { + Notification::route('mail', $email)->notify( + new CapacityAlertNotification( + $alertConfig, + $alerts, + ) + ); + $emailDelivered = true; + } catch (\Throwable $e) { + Log::warning( + 'Failed to send configured capacity alert email', + [ + 'alert_config_id' => $config->id, + 'recipient_email' => $email, + 'error' => $e->getMessage(), + ] + ); + $lastError = $e->getMessage(); + $this->reportThrowable($e); + } + } + if ($emailDelivered) { $channelsOk[] = 'email'; } else { @@ -196,8 +281,8 @@ private function sendNotifications(object $config, array $availability, array $a 'title' => 'Resource Usage Alert', 'color' => $alertColor, 'fields' => array_map(fn ($alert) => [ - 'name' => ucfirst($alert['type']) . ' - ' . ucfirst($alert['resource']), - 'value' => round($alert['utilization'], 1) . '% utilized', + 'name' => ucfirst($alert['type']).' - '.ucfirst($alert['resource']), + 'value' => round($alert['utilization'], 1).'% utilized', 'inline' => true, ], $alerts), 'footer' => [ @@ -396,7 +481,7 @@ public function notifyProvisioningFailure(array $snapshot): void } $this->safeAudit( - $operation . '_failure_alerted', + $operation.'_failure_alerted', 'resource_reservation', (int) ($snapshot['reservation_id'] ?? 0), [ @@ -498,6 +583,38 @@ private function getAdminRecipients(): Collection return User::whereNotNull('role_id')->get(); } + /** + * @return array + */ + private function configuredNotificationEmails(object $config): array + { + $emails = $config->notification_emails ?? []; + if (is_string($emails)) { + $decoded = json_decode($emails, true); + $emails = is_array($decoded) ? $decoded : []; + } + if (! is_array($emails)) { + return []; + } + + $normalized = []; + foreach ($emails as $email) { + if (! is_string($email)) { + continue; + } + + $email = strtolower(trim($email)); + if ( + $email !== '' + && filter_var($email, FILTER_VALIDATE_EMAIL) !== false + ) { + $normalized[$email] = $email; + } + } + + return array_values($normalized); + } + private function hydrateAlertConfig(object $config): AlertConfig { if ($config instanceof AlertConfig) { diff --git a/Services/AllocationSelectionService.php b/Services/AllocationSelectionService.php index 5b47774..01ab2f7 100644 --- a/Services/AllocationSelectionService.php +++ b/Services/AllocationSelectionService.php @@ -70,8 +70,7 @@ public function select( usort( $available, - fn (array $left, array $right): int => - $left['id'] <=> $right['id'] + fn (array $left, array $right): int => $left['id'] <=> $right['id'] ); $ids = array_column($available, 'id'); @@ -108,8 +107,7 @@ public function select( } usort( $candidates, - fn (array $left, array $right): int => - min(array_column($left, 'id')) + fn (array $left, array $right): int => min(array_column($left, 'id')) <=> min(array_column($right, 'id')) ); @@ -157,15 +155,13 @@ private function selectFromPool( } foreach ($requiredPorts as $requiredPort) { if (collect($selected)->contains( - fn (array $allocation): bool => - $allocation['port'] === $requiredPort + fn (array $allocation): bool => $allocation['port'] === $requiredPort )) { continue; } $matches = array_values(array_filter( $available, - fn (array $allocation): bool => - $allocation['port'] === $requiredPort + fn (array $allocation): bool => $allocation['port'] === $requiredPort && ! isset($selectedIds[$allocation['id']]) )); if ($matches === []) { diff --git a/Services/AuditLogService.php b/Services/AuditLogService.php index 42ea642..a1dca75 100644 --- a/Services/AuditLogService.php +++ b/Services/AuditLogService.php @@ -24,7 +24,7 @@ public function log( $user = Auth::user(); return DB::table('ptero_audit_logs')->insertGetId([ - 'user_id' => $user?->id ?? 0, + 'user_id' => $user?->id, 'user_name' => $user?->name ?? 'System', 'user_email' => $user?->email ?? 'system@localhost', 'action' => $action, diff --git a/Services/ConfigOptionSetupService.php b/Services/ConfigOptionSetupService.php index ceb785f..7c0ce31 100644 --- a/Services/ConfigOptionSetupService.php +++ b/Services/ConfigOptionSetupService.php @@ -151,8 +151,7 @@ private function buildResourceMetadata( string $resourceType, array $config, array $defaults - ): array - { + ): array { $pricingModel = $config['pricing_model'] ?? 'linear'; $divisor = $defaults['display_divisor'] ?? 1; @@ -198,7 +197,7 @@ private function buildResourceMetadata( } $errors = []; - (new DynamicSliderMetadataRule())->validate( + (new DynamicSliderMetadataRule)->validate( 'metadata', $metadata, function (string $message) use (&$errors): void { @@ -433,8 +432,7 @@ private function findExistingOption( int $productId, string $name, bool $failOnConflict = true - ): ?ConfigOption - { + ): ?ConfigOption { $name = strtolower($name); $candidates = $this->productOptions($productId) ->filter(function (ConfigOption $option) use ($name): bool { diff --git a/Services/ProductResourceConfigurationService.php b/Services/ProductResourceConfigurationService.php index 6d8d25d..8c7af0e 100644 --- a/Services/ProductResourceConfigurationService.php +++ b/Services/ProductResourceConfigurationService.php @@ -349,8 +349,7 @@ private function staticLocation(mixed $rawLocations): int private function allocationRequirements( mixed $raw, int $additionalAllocations = 0 - ): array - { + ): array { if ($raw === null || $raw === '') { $mappings = [[ 'environment_key' => 'SERVER_PORT', @@ -503,8 +502,7 @@ private function portRanges(mixed $raw): array usort( $ranges, - fn (array $left, array $right): int => - [$left['from'], $left['to']] <=> [$right['from'], $right['to']] + fn (array $left, array $right): int => [$left['from'], $left['to']] <=> [$right['from'], $right['to']] ); $merged = []; foreach ($ranges as $range) { diff --git a/Services/QuoteRateLimitConfigurationService.php b/Services/QuoteRateLimitConfigurationService.php index 18b4232..b7c1fb7 100644 --- a/Services/QuoteRateLimitConfigurationService.php +++ b/Services/QuoteRateLimitConfigurationService.php @@ -19,9 +19,7 @@ class QuoteRateLimitConfigurationService /** * @param array|null $config */ - public function __construct(private readonly ?array $config = null) - { - } + public function __construct(private readonly ?array $config = null) {} /** * @return array{per_ip: int, global: int, panel_identity: string} diff --git a/Services/QuoteRateLimiterService.php b/Services/QuoteRateLimiterService.php index db8fdf6..31b2f37 100644 --- a/Services/QuoteRateLimiterService.php +++ b/Services/QuoteRateLimiterService.php @@ -12,8 +12,7 @@ class QuoteRateLimiterService public function __construct( private readonly QuoteRateLimitConfigurationService $configuration - ) { - } + ) {} public function register(): void { diff --git a/Services/ReservationConfigurationService.php b/Services/ReservationConfigurationService.php index 8b152d5..fd57a09 100644 --- a/Services/ReservationConfigurationService.php +++ b/Services/ReservationConfigurationService.php @@ -314,8 +314,7 @@ public function withCustomer( array $payload, int $customerId, string $customerEmail - ): array - { + ): array { $payload['customer_id'] = $customerId; $payload['provisioning_identity']['user_external_id'] = $this->pterodactylUserExternalId($customerId); @@ -466,8 +465,7 @@ public function verifiedAllocationSnapshot( } usort( $expected, - fn (array $left, array $right): int => - $left['allocation_id'] <=> $right['allocation_id'] + fn (array $left, array $right): int => $left['allocation_id'] <=> $right['allocation_id'] ); $claimRows = collect($claims)->values(); @@ -488,12 +486,10 @@ public function verifiedAllocationSnapshot( $status = (string) ($reservation->status ?? ''); $releaseStateIsValid = match ($status) { 'pending', 'paid_committed' => ! $claimRows->contains( - fn (object $allocation): bool => - $allocation->released_at !== null + fn (object $allocation): bool => $allocation->released_at !== null ), 'confirmed' => ! $claimRows->contains( - fn (object $allocation): bool => - $allocation->released_at === null + fn (object $allocation): bool => $allocation->released_at === null ), default => false, }; @@ -541,8 +537,6 @@ private function canonicalMoney(mixed $unitPrice, int $quantity): string * intentionally not recomputed here: administrators may edit them while a * seven-day quote is open. The signed reservation remains authoritative * and the provisioner overrides placement and resources from that snapshot. - * - * @param object $reservation */ public function assertServiceMatches(Service $service, object $reservation): void { diff --git a/Services/ReservationService.php b/Services/ReservationService.php index 80dfefe..44072af 100644 --- a/Services/ReservationService.php +++ b/Services/ReservationService.php @@ -14,6 +14,7 @@ use App\Services\Service\CapacityConfigurationLockService; use App\Services\Service\FulfillmentStatusTransitionService; use App\Services\Service\ProductStockService; +use App\Services\Service\ServiceJobDispatchService; use App\Support\StrictInteger; use Carbon\Carbon; use Carbon\CarbonInterface; @@ -30,6 +31,8 @@ class ReservationService { use AuditsExtensionActions; + private const MAX_ADMIN_EXTENSION_MINUTES = 60; + private const PROVISIONING_LEASE_MINUTES = 5; private const RETRY_DELAYS_SECONDS = [15, 60, 300, 900, 1800, 3600, 10800]; @@ -472,8 +475,7 @@ public function bindCartItemToService( if ( $lockedInvoice !== null && ! $invoiceItems->contains( - fn ($item): bool => - (int) $item->reference_id === (int) $lockedService->id + fn ($item): bool => (int) $item->reference_id === (int) $lockedService->id && (string) $item->reference_type === $lockedService->getMorphClass() && (int) $item->quantity === (int) $lockedService->quantity ) @@ -871,8 +873,7 @@ public function completeProvisioning( int|Service $service, ?string $leaseId = null, array $externalServer = [] - ): bool - { + ): bool { $serviceId = $service instanceof Service ? (int) $service->id : $service; return DB::transaction(function () use ($serviceId, $leaseId, $externalServer) { @@ -963,8 +964,7 @@ public function failProvisioning( int $serviceId, ?string $leaseId, \Throwable $exception - ): void - { + ): void { $attempts = (int) $this->checkoutCommitmentQuery($serviceId) ->value('provisioning_attempts'); $delay = self::RETRY_DELAYS_SECONDS[ @@ -1010,7 +1010,7 @@ public function requestServiceCancellation(Service $service): bool 'provisioning_lease_id' => null, 'admin_notes' => 'Service cancelled before payment.', 'updated_at' => now(), - ]); + ]); $this->releaseAllocationClaims((int) $reservation->id); $this->releaseProductStockOnce($reservation, $lockedService); $lockedService->status = Service::STATUS_CANCELLED; @@ -1134,10 +1134,8 @@ public function pinCancellationServerIdentity( $storedIdentity = [ 'external_server_id' => $reservation->external_server_id, 'external_user_id' => $reservation->external_user_id, - 'external_server_uuid' => - $reservation->external_server_uuid, - 'external_server_identifier' => - $reservation->external_server_identifier, + 'external_server_uuid' => $reservation->external_server_uuid, + 'external_server_identifier' => $reservation->external_server_identifier, ]; $hasStoredIdentity = collect($storedIdentity) ->contains(fn ($value): bool => $value !== null); @@ -1325,8 +1323,7 @@ public function serverLifecycleIdentity(int|Service $service): ?array ? (int) $reservation->external_user_id : null, 'external_server_uuid' => $reservation->external_server_uuid, - 'external_server_identifier' => - $reservation->external_server_identifier, + 'external_server_identifier' => $reservation->external_server_identifier, 'external_server_external_id' => (string) $serviceId, 'user_external_id' => $provisioning['user_external_id'] ?? null, 'user_email' => $provisioning['user_email'] ?? null, @@ -1530,10 +1527,10 @@ public function cancel( ->where('status', 'pending') ->whereNull('service_id') ->update([ - 'status' => 'cancelled', - 'admin_notes' => $reason, - 'updated_at' => now(), - ]); + 'status' => 'cancelled', + 'admin_notes' => $reason, + 'updated_at' => now(), + ]); if ($updated !== 1) { throw new \RuntimeException( 'The reservation changed while cancellation was being committed.' @@ -1566,31 +1563,106 @@ public function cancel( */ public function extend(string $token, int $additionalMinutes = 15, ?User $actor = null): bool { - $reservation = ResourceReservation::query()->where('token', $token)->first(); - if ($reservation === null) { - return false; + if ( + $additionalMinutes < 1 + || $additionalMinutes > self::MAX_ADMIN_EXTENSION_MINUTES + ) { + throw new \InvalidArgumentException( + 'A reservation extension must be between 1 and 60 minutes.' + ); } - if ($actor !== null) { - Gate::forUser($actor)->authorize('extend', $reservation); - } + $extended = DB::transaction(function () use ( + $token, + $additionalMinutes, + $actor + ): ?array { + $reservation = ResourceReservation::query() + ->where('token', $token) + ->lockForUpdate() + ->first(); + if ($reservation === null) { + return null; + } - if ($reservation->status !== 'pending') { - return false; - } + if ($actor !== null) { + Gate::forUser($actor)->authorize('extend', $reservation); + } + + if ( + $reservation->status !== ResourceReservation::STATUS_PENDING + || $reservation->service_id !== null + || $reservation->invoice_id !== null + ) { + return null; + } + + $now = now(); + $currentExpiresAt = $reservation->expires_at?->copy(); + $maximumExpiresAt = $now->copy()->addMinutes( + self::MAX_ADMIN_EXTENSION_MINUTES + ); + if ( + $currentExpiresAt === null + || ! $currentExpiresAt->greaterThan($now) + || ! $currentExpiresAt->lessThan($maximumExpiresAt) + ) { + return null; + } - if ($reservation->service_id !== null || $reservation->invoice_id !== null) { + $requestedExpiresAt = $currentExpiresAt + ->copy() + ->addMinutes($additionalMinutes); + $newExpiresAt = $requestedExpiresAt->greaterThan( + $maximumExpiresAt + ) + ? $maximumExpiresAt + : $requestedExpiresAt; + $updated = DB::table('ptero_resource_reservations') + ->where('id', $reservation->id) + ->where( + 'status', + ResourceReservation::STATUS_PENDING + ) + ->whereNull('service_id') + ->whereNull('invoice_id') + ->update([ + 'expires_at' => $newExpiresAt, + 'guaranteed_until' => $newExpiresAt, + 'updated_at' => $now, + ]); + if ($updated !== 1) { + throw new \RuntimeException( + 'The reservation changed while its extension was being committed.' + ); + } + + return [ + 'id' => (int) $reservation->id, + 'node_id' => (int) $reservation->node_id, + 'previous_expires_at' => $currentExpiresAt->toIso8601String(), + 'expires_at' => $newExpiresAt->toIso8601String(), + 'capped' => $requestedExpiresAt->greaterThan( + $maximumExpiresAt + ), + ]; + }, 5); + if ($extended === null) { return false; } - $reservation->expires_at = $reservation->expires_at->addMinutes($additionalMinutes); - $reservation->guaranteed_until = $reservation->expires_at; - $reservation->save(); - - $this->safeAudit('reservation_extended', 'resource_reservation', $reservation->id, [ - 'additional_minutes' => $additionalMinutes, - 'node_id' => $reservation->node_id, - ]); + $this->safeAudit( + 'reservation_extended', + 'resource_reservation', + $extended['id'], + [ + 'additional_minutes' => $additionalMinutes, + 'previous_expires_at' => $extended['previous_expires_at'], + 'expires_at' => $extended['expires_at'], + 'capped' => $extended['capped'], + 'node_id' => $extended['node_id'], + ] + ); return true; } @@ -1651,10 +1723,38 @@ public function getStatistics(string $period = '30d'): array ->pluck('count', 'status') ->toArray(); - $revenue = DB::table('ptero_resource_reservations') + $revenueRows = DB::table('ptero_resource_reservations') ->where('created_at', '>=', $startDate) ->where('status', 'confirmed') - ->sum('calculated_price'); + ->selectRaw('currency_code, SUM(calculated_price) as total') + ->groupBy('currency_code') + ->orderBy('currency_code') + ->get(); + $revenueCents = []; + foreach ($revenueRows as $row) { + $currency = strtoupper(trim((string) $row->currency_code)); + $cents = $this->moneyCents($row->total); + if ($cents === null) { + throw new \RuntimeException( + 'Confirmed reservation revenue contains an invalid amount.' + ); + } + if (preg_match('/^[A-Z]{3}$/D', $currency) !== 1) { + $currency = 'UNSPECIFIED'; + } + $current = $revenueCents[$currency] ?? 0; + if ($current > PHP_INT_MAX - $cents) { + throw new \RuntimeException( + 'Confirmed reservation revenue exceeds the supported range.' + ); + } + $revenueCents[$currency] = $current + $cents; + } + ksort($revenueCents); + $revenueByCurrency = array_map( + fn (int $cents): string => $this->moneyFromCents($cents), + $revenueCents + ); $average = DB::table('ptero_resource_reservations') ->where('created_at', '>=', $startDate) @@ -1671,7 +1771,7 @@ public function getStatistics(string $period = '30d'): array 'period' => $period, 'total' => $total, 'by_status' => $stats, - 'confirmed_revenue' => $revenue, + 'confirmed_revenue_by_currency' => $revenueByCurrency, 'conversion_rate' => ($confirmed + $expired + $cancelled) > 0 ? round($confirmed / ($confirmed + $expired + $cancelled) * 100, 1) : 0, @@ -1683,125 +1783,219 @@ public function getStatistics(string $period = '30d'): array ]; } - public function cleanupExpired(): int + public function cleanupExpired(int $limit = 100): int { - $candidateIds = DB::table('ptero_resource_reservations') - ->where('purpose', 'checkout') - ->where('status', 'pending') - ->whereRaw('COALESCE(guaranteed_until, expires_at) <= ?', [now()]) - ->pluck('id'); - $count = 0; - - foreach ($candidateIds as $candidateId) { - $changed = DB::transaction(function () use ($candidateId) { - $candidate = DB::table('ptero_resource_reservations')->where('id', $candidateId)->first(); - if ($candidate === null) { - return false; - } + $limit = max(1, min($limit, 500)); + $count = app(SchedulerHealthService::class)->processEligibleRows( + SchedulerHealthService::TASK_EXPIRE_CHECKOUT, + 'resource_reservation', + $limit, + fn (): Builder => DB::table('ptero_resource_reservations') + ->where('purpose', 'checkout') + ->where('status', 'pending') + ->whereRaw( + 'COALESCE(guaranteed_until, expires_at) <= ?', + [now()] + ), + function (int $candidateId): bool { + return DB::transaction(function () use ($candidateId) { + $candidate = DB::table('ptero_resource_reservations')->where('id', $candidateId)->first(); + if ($candidate === null) { + return false; + } - $invoice = $candidate->invoice_id !== null - ? Invoice::query()->whereKey($candidate->invoice_id)->lockForUpdate()->first() - : null; - $itemSnapshotIds = $invoice !== null - ? $invoice->items()->orderBy('id')->pluck('id') - : collect(); - $serviceIds = $invoice !== null - ? $invoice->items() - ->where('reference_type', Service::class) - ->pluck('reference_id') - ->merge( - DB::table('ptero_resource_reservations') - ->where('purpose', 'checkout') - ->where('invoice_id', $invoice->id) - ->pluck('service_id') + $invoice = $candidate->invoice_id !== null + ? Invoice::query()->whereKey($candidate->invoice_id)->lockForUpdate()->first() + : null; + $itemSnapshotIds = $invoice !== null + ? $invoice->items()->orderBy('id')->pluck('id') + : collect(); + $serviceIds = $invoice !== null + ? $invoice->items() + ->where('reference_type', Service::class) + ->pluck('reference_id') + ->merge( + DB::table('ptero_resource_reservations') + ->where('purpose', 'checkout') + ->where('invoice_id', $invoice->id) + ->pluck('service_id') + ) + ->filter() + ->map(fn ($id) => (int) $id) + ->unique() + ->sort() + ->values() + : collect(array_filter([(int) ($candidate->service_id ?? 0)])); + $services = Service::query() + ->whereKey($serviceIds->all()) + ->orderBy('id') + ->lockForUpdate() + ->get(); + $service = $services->firstWhere('id', (int) $candidate->service_id); + $reservations = DB::table('ptero_resource_reservations') + ->where('purpose', 'checkout') + ->when( + $invoice !== null, + fn (Builder $query) => $query->where( + 'invoice_id', + $invoice->id + ), + fn (Builder $query) => $query->where('id', $candidateId) ) - ->filter() - ->map(fn ($id) => (int) $id) - ->unique() - ->sort() - ->values() - : collect(array_filter([(int) ($candidate->service_id ?? 0)])); - $services = Service::query() - ->whereKey($serviceIds->all()) - ->orderBy('id') - ->lockForUpdate() - ->get(); - $service = $services->firstWhere('id', (int) $candidate->service_id); - $reservations = DB::table('ptero_resource_reservations') - ->where('purpose', 'checkout') - ->when( - $invoice !== null, - fn (Builder $query) => $query->where( - 'invoice_id', - $invoice->id - ), - fn (Builder $query) => $query->where('id', $candidateId) - ) - ->orderBy('id') - ->lockForUpdate() - ->get(); - $reservation = $reservations->firstWhere('id', $candidateId); - $lockedItems = $invoice !== null - ? $invoice->items() ->orderBy('id') ->lockForUpdate() - ->get() - : collect(); - if ( - $invoice !== null - && $lockedItems->pluck('id')->all() - !== $itemSnapshotIds->all() - ) { - throw new \RuntimeException( - 'The capacity invoice obligations changed while expiry was acquiring its locks.' - ); - } + ->get(); + $reservation = $reservations->firstWhere('id', $candidateId); + $lockedItems = $invoice !== null + ? $invoice->items() + ->orderBy('id') + ->lockForUpdate() + ->get() + : collect(); + if ( + $invoice !== null + && $lockedItems->pluck('id')->all() + !== $itemSnapshotIds->all() + ) { + throw new \RuntimeException( + 'The capacity invoice obligations changed while expiry was acquiring its locks.' + ); + } - if ( - $reservation === null - || $reservation->status !== ResourceReservation::STATUS_PENDING - || Carbon::parse( - $reservation->guaranteed_until ?? $reservation->expires_at - )->isFuture() - ) { - return false; - } + if ( + $reservation === null + || $reservation->status !== ResourceReservation::STATUS_PENDING + || Carbon::parse( + $reservation->guaranteed_until ?? $reservation->expires_at + )->isFuture() + ) { + return false; + } - if ($invoice?->status === Invoice::STATUS_PAID && $service !== null) { - $reason = 'A paid invoice was found after its capacity guarantee expired before fulfillment was committed.'; - $snapshot = [ - 'reservation_id' => (int) $reservation->id, - 'service_id' => (int) $service->id, - 'invoice_id' => (int) $invoice->id, - 'node_id' => (int) $reservation->node_id, - 'memory' => (int) $reservation->memory, - 'cpu' => (int) $reservation->cpu, - 'disk' => (int) $reservation->disk, - 'attempts' => (int) $reservation->provisioning_attempts, - 'error' => $reason, - ]; - $expiringReservations = $reservations->where( - 'status', - ResourceReservation::STATUS_PENDING - ); - foreach ($expiringReservations as $expiringReservation) { + if ($invoice?->status === Invoice::STATUS_PAID && $service !== null) { + $reason = 'A paid invoice was found after its capacity guarantee expired before fulfillment was committed.'; + $snapshot = [ + 'reservation_id' => (int) $reservation->id, + 'service_id' => (int) $service->id, + 'invoice_id' => (int) $invoice->id, + 'node_id' => (int) $reservation->node_id, + 'memory' => (int) $reservation->memory, + 'cpu' => (int) $reservation->cpu, + 'disk' => (int) $reservation->disk, + 'attempts' => (int) $reservation->provisioning_attempts, + 'error' => $reason, + ]; + $expiringReservations = $reservations->where( + 'status', + ResourceReservation::STATUS_PENDING + ); + foreach ($expiringReservations as $expiringReservation) { + DB::table('ptero_resource_reservations') + ->where('id', $expiringReservation->id) + ->update([ + 'status' => ResourceReservation::STATUS_EXPIRED, + 'last_provisioning_error' => $reason, + 'failure_alerted_at' => $expiringReservation->failure_alerted_at ?? now(), + 'admin_notes' => $reason, + 'updated_at' => now(), + ]); + $this->releaseAllocationClaims( + (int) $expiringReservation->id + ); + } + foreach ($services as $linkedService) { + if ($linkedService->status !== Service::STATUS_PENDING) { + continue; + } + $linkedReservation = $reservations->firstWhere( + 'service_id', + $linkedService->id + ); + if ($linkedReservation !== null) { + $this->releaseProductStockOnce( + $linkedReservation, + $linkedService + ); + } else { + app(ProductStockService::class)->release( + $linkedService + ); + } + $linkedService->status = Service::STATUS_PROVISIONING_FAILED; + $this->persistFulfillmentService($linkedService); + } + + if ($reservation->failure_alerted_at === null) { + DB::afterCommit(function () use ($snapshot, $reason) { + $alerts = app(AlertService::class); + if (method_exists($alerts, 'notifyShortfall')) { + $alerts->notifyShortfall( + $snapshot['service_id'], + $snapshot['invoice_id'], + $snapshot, + $reason + ); + } else { + $alerts->notifyProvisioningFailure($snapshot); + } + }); + } + + return true; + } + + if ( + $invoice?->status === Invoice::STATUS_PAID + || $service?->status === 'provisioning' + ) { + throw new \RuntimeException( + 'An expired hold cannot be reclaimed after payment or provisioning begins.' + ); + } + + $paymentAttention = $invoice !== null + && $invoice->status === Invoice::STATUS_PENDING + && app(CapacityInvoicePaymentService::class) + ->hasInFlightOrSucceededPayment($invoice); + + foreach ( + $reservations->where( + 'status', + ResourceReservation::STATUS_PENDING + ) as $expiringReservation + ) { DB::table('ptero_resource_reservations') ->where('id', $expiringReservation->id) ->update([ - 'status' => ResourceReservation::STATUS_EXPIRED, - 'last_provisioning_error' => $reason, - 'failure_alerted_at' => $expiringReservation->failure_alerted_at ?? now(), - 'admin_notes' => $reason, - 'updated_at' => now(), - ]); + 'status' => ResourceReservation::STATUS_EXPIRED, + 'provisioning_started_at' => null, + 'provisioning_lease_id' => null, + 'updated_at' => now(), + ]); $this->releaseAllocationClaims( (int) $expiringReservation->id ); } + + if ($paymentAttention) { + app(CapacityInvoicePaymentService::class)->requireAttention( + $invoice, + 'The seven-day capacity guarantee expired after a partial or in-flight payment. Capacity was released; refund or account-credit review is required.' + ); + } elseif ($invoice !== null && $invoice->status === Invoice::STATUS_PENDING) { + app(CancelInvoiceService::class) + ->markCancelledAfterFulfillment($invoice); + } foreach ($services as $linkedService) { if ($linkedService->status !== Service::STATUS_PENDING) { continue; } + + $linkedService->status = $paymentAttention + ? Service::STATUS_PROVISIONING_FAILED + : Service::STATUS_CANCELLED; + $this->persistFulfillmentService($linkedService); + $linkedReservation = $reservations->firstWhere( 'service_id', $linkedService->id @@ -1812,106 +2006,14 @@ public function cleanupExpired(): int $linkedService ); } else { - app(ProductStockService::class)->release( - $linkedService - ); + app(ProductStockService::class)->release($linkedService); } - $linkedService->status = Service::STATUS_PROVISIONING_FAILED; - $this->persistFulfillmentService($linkedService); - } - - if ($reservation->failure_alerted_at === null) { - DB::afterCommit(function () use ($snapshot, $reason) { - $alerts = app(AlertService::class); - if (method_exists($alerts, 'notifyShortfall')) { - $alerts->notifyShortfall( - $snapshot['service_id'], - $snapshot['invoice_id'], - $snapshot, - $reason - ); - } else { - $alerts->notifyProvisioningFailure($snapshot); - } - }); } return true; - } - - if ( - $invoice?->status === Invoice::STATUS_PAID - || $service?->status === 'provisioning' - ) { - throw new \RuntimeException( - 'An expired hold cannot be reclaimed after payment or provisioning begins.' - ); - } - - $paymentAttention = $invoice !== null - && $invoice->status === Invoice::STATUS_PENDING - && app(CapacityInvoicePaymentService::class) - ->hasInFlightOrSucceededPayment($invoice); - - foreach ( - $reservations->where( - 'status', - ResourceReservation::STATUS_PENDING - ) as $expiringReservation - ) { - DB::table('ptero_resource_reservations') - ->where('id', $expiringReservation->id) - ->update([ - 'status' => ResourceReservation::STATUS_EXPIRED, - 'provisioning_started_at' => null, - 'provisioning_lease_id' => null, - 'updated_at' => now(), - ]); - $this->releaseAllocationClaims( - (int) $expiringReservation->id - ); - } - - if ($paymentAttention) { - app(CapacityInvoicePaymentService::class)->requireAttention( - $invoice, - 'The seven-day capacity guarantee expired after a partial or in-flight payment. Capacity was released; refund or account-credit review is required.' - ); - } elseif ($invoice !== null && $invoice->status === Invoice::STATUS_PENDING) { - app(CancelInvoiceService::class) - ->markCancelledAfterFulfillment($invoice); - } - foreach ($services as $linkedService) { - if ($linkedService->status !== Service::STATUS_PENDING) { - continue; - } - - $linkedService->status = $paymentAttention - ? Service::STATUS_PROVISIONING_FAILED - : Service::STATUS_CANCELLED; - $this->persistFulfillmentService($linkedService); - - $linkedReservation = $reservations->firstWhere( - 'service_id', - $linkedService->id - ); - if ($linkedReservation !== null) { - $this->releaseProductStockOnce( - $linkedReservation, - $linkedService - ); - } else { - app(ProductStockService::class)->release($linkedService); - } - } - - return true; - }, 5); - - if ($changed) { - $count++; + }, 5); } - } + ); if ($count > 0) { $this->safeAudit('reservations_expired_batch', 'resource_reservation', 0, [ @@ -1929,85 +2031,110 @@ public function cleanupExpired(): int */ public function reconcileStalledPaidCommitments(int $limit = 100): int { + $limit = max(1, min($limit, 500)); $cutoff = now()->subMinutes(self::PROVISIONING_LEASE_MINUTES); - $reservationIds = DB::table('ptero_resource_reservations') - ->where('status', ResourceReservation::STATUS_PAID_COMMITTED) - ->whereNull('cancellation_requested_at') - ->where(function (Builder $query) { - $query->whereNull('next_provisioning_attempt_at') - ->orWhere('next_provisioning_attempt_at', '<=', now()); - }) - ->where(function (Builder $query) use ($cutoff) { - $query->whereNull('provisioning_started_at') - ->orWhere('provisioning_started_at', '<=', $cutoff); - }) - ->orderBy('next_provisioning_attempt_at') - ->limit($limit) - ->pluck('id'); - - $dispatched = 0; - foreach ($reservationIds as $reservationId) { - $service = DB::transaction(function () use ($reservationId, $cutoff) { - $candidate = DB::table('ptero_resource_reservations') - ->where('id', $reservationId) - ->first(['service_id']); - if ($candidate?->service_id === null) { - return null; - } - $service = Service::query() - ->whereKey($candidate->service_id) - ->lockForUpdate() - ->first(); - $reservation = DB::table('ptero_resource_reservations') - ->where('id', $reservationId) - ->lockForUpdate() - ->first(); + return app(SchedulerHealthService::class)->processEligibleRows( + SchedulerHealthService::TASK_RECONCILE_CHECKOUT, + 'resource_reservation', + $limit, + fn (): Builder => DB::table('ptero_resource_reservations') + ->where( + 'status', + ResourceReservation::STATUS_PAID_COMMITTED + ) + ->whereNull('cancellation_requested_at') + ->where(function (Builder $query): void { + $query->whereNull('next_provisioning_attempt_at') + ->orWhere( + 'next_provisioning_attempt_at', + '<=', + now() + ); + }) + ->where(function (Builder $query) use ($cutoff): void { + $query->whereNull('provisioning_started_at') + ->orWhere('provisioning_started_at', '<=', $cutoff); + }), + function (int $reservationId) use ($cutoff): bool { + $service = DB::transaction( + function () use ($reservationId, $cutoff) { + $candidate = DB::table( + 'ptero_resource_reservations' + ) + ->where('id', $reservationId) + ->first(['service_id']); + if ($candidate?->service_id === null) { + return null; + } + + $service = Service::query() + ->whereKey($candidate->service_id) + ->lockForUpdate() + ->first(); + $reservation = DB::table( + 'ptero_resource_reservations' + ) + ->where('id', $reservationId) + ->lockForUpdate() + ->first(); + if ( + $service === null + || $service->status + !== Service::STATUS_PROVISIONING + || $reservation === null + || $reservation->status + !== ResourceReservation::STATUS_PAID_COMMITTED + || $reservation->cancellation_requested_at !== null + || ( + $reservation->next_provisioning_attempt_at + !== null + && Carbon::parse( + $reservation + ->next_provisioning_attempt_at + )->isFuture() + ) + || ( + $reservation->provisioning_started_at !== null + && Carbon::parse( + $reservation->provisioning_started_at + )->greaterThan($cutoff) + ) + ) { + return null; + } + + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'provisioning_started_at' => null, + 'provisioning_lease_id' => null, + 'next_provisioning_attempt_at' => now() + ->addMinutes(10), + 'updated_at' => now(), + ]); + + return $service; + }, + 5 + ); + if ( $service === null - || $service->status !== Service::STATUS_PROVISIONING - || $reservation === null - || $reservation->status !== ResourceReservation::STATUS_PAID_COMMITTED - || $reservation->cancellation_requested_at !== null - || ( - $reservation->next_provisioning_attempt_at !== null - && Carbon::parse($reservation->next_provisioning_attempt_at)->isFuture() - ) - || ( - $reservation->provisioning_started_at !== null - && Carbon::parse($reservation->provisioning_started_at)->greaterThan($cutoff) - ) + || ! class_exists(ServiceJobDispatchService::class) ) { - return null; + return false; } - DB::table('ptero_resource_reservations') - ->where('id', $reservationId) - ->update([ - 'provisioning_started_at' => null, - 'provisioning_lease_id' => null, - 'next_provisioning_attempt_at' => now()->addMinutes(10), - 'updated_at' => now(), - ]); - - return $service; - }, 5); - - if ($service === null) { - continue; - } + app(ServiceJobDispatchService::class) + ->requestCreate($service); - if (class_exists(\App\Jobs\Server\CreateJob::class)) { - \App\Jobs\Server\CreateJob::dispatch($service); - $dispatched++; + return true; } - } - - return $dispatched; + ); } /** - * @param object $reservation * @param array $snapshot */ private function matchesSnapshot(object $reservation, array $snapshot): bool @@ -2031,7 +2158,6 @@ private function matchesSnapshot(object $reservation, array $snapshot): bool } /** - * @param object $reservation * @return array{ * reservation_id: int, * panel_identity: string, @@ -2052,8 +2178,7 @@ private function provisioningContext( object $reservation, bool $alreadyConsumed, ?string $leaseId = null - ): array - { + ): array { try { $payload = json_decode( (string) $reservation->configuration_payload, @@ -2070,10 +2195,10 @@ private function provisioningContext( $identity = is_array($payload) ? (array) ($payload['provisioning_identity'] ?? []) : []; - $nestId = \App\Support\StrictInteger::parse( + $nestId = StrictInteger::parse( $identity['nest_id'] ?? null ); - $eggId = \App\Support\StrictInteger::parse( + $eggId = StrictInteger::parse( $identity['egg_id'] ?? null ); $userExternalId = $identity['user_external_id'] ?? null; @@ -2155,13 +2280,11 @@ private function mapAllocationRequirements(array $available, array $requirements $requirements = array_values(array_merge( array_filter( $requirements, - fn (array $requirement): bool => - ($requirement['requested_port'] ?? null) !== null + fn (array $requirement): bool => ($requirement['requested_port'] ?? null) !== null ), array_filter( $requirements, - fn (array $requirement): bool => - ($requirement['requested_port'] ?? null) === null + fn (array $requirement): bool => ($requirement['requested_port'] ?? null) === null ) )); @@ -2251,7 +2374,6 @@ private function externalServerIdentity(array $attributes): array } /** - * @param object $reservation * @return array */ private function buildCancellationReconciliationContext( @@ -2338,8 +2460,7 @@ private function buildCancellationReconciliationContext( return [ 'reservation_id' => (int) $reservation->id, - 'configuration_fingerprint' => - (string) $reservation->configuration_fingerprint, + 'configuration_fingerprint' => (string) $reservation->configuration_fingerprint, 'status' => (string) $reservation->status, 'panel_identity' => (string) $reservation->panel_identity, 'external_server_external_id' => (string) $service->id, @@ -2467,16 +2588,13 @@ private function assertCancellationServerMatchesContext( $reserved = collect($context['allocations'] ?? []); $reservedIds = $reserved - ->map(fn (array $allocation): int => - (int) ($allocation['allocation_id'] ?? 0)) + ->map(fn (array $allocation): int => (int) ($allocation['allocation_id'] ?? 0)) ->sort() ->values() ->all(); $primaryIds = $reserved - ->filter(fn (array $allocation): bool => - (bool) ($allocation['is_primary'] ?? false)) - ->map(fn (array $allocation): int => - (int) ($allocation['allocation_id'] ?? 0)) + ->filter(fn (array $allocation): bool => (bool) ($allocation['is_primary'] ?? false)) + ->map(fn (array $allocation): int => (int) ($allocation['allocation_id'] ?? 0)) ->values(); if ( $reservedIds === [] @@ -2497,7 +2615,7 @@ private function assertCancellationServerMatchesContext( */ private function capacityScopeKey(array $scope): string { - return $scope['panel_identity'] . ':' . $scope['location_id']; + return $scope['panel_identity'].':'.$scope['location_id']; } private function checkoutCommitmentQuery(int $serviceId): Builder @@ -2598,6 +2716,19 @@ private function moneyCents(mixed $value): ?int + (int) str_pad(substr($fraction, 0, 2), 2, '0'); } + private function moneyFromCents(int $cents): string + { + if ($cents < 0) { + throw new \RuntimeException( + 'Reservation revenue cannot be negative.' + ); + } + + return intdiv($cents, 100) + .'.' + .str_pad((string) ($cents % 100), 2, '0', STR_PAD_LEFT); + } + /** * Prove that the allocation claim rows are an exact materialization of the * fingerprinted payload before any external request can use them. diff --git a/Services/ResourceCalculationService.php b/Services/ResourceCalculationService.php index 87e060a..58fd077 100644 --- a/Services/ResourceCalculationService.php +++ b/Services/ResourceCalculationService.php @@ -254,8 +254,7 @@ private function buildLocationAvailability( $nodeServers = $servers[$nodeId] ?? []; $assignedServerAllocationIds = collect($nodeServers) ->flatMap( - fn (array $server): array => - $server['assigned_allocation_ids'] ?? [] + fn (array $server): array => $server['assigned_allocation_ids'] ?? [] ) ->map(fn ($id): int => (int) $id) ->unique() @@ -272,8 +271,7 @@ private function buildLocationAvailability( ) ) ->map( - fn (array $allocation): string => - $this->canonicalIp((string) $allocation['ip']) + fn (array $allocation): string => $this->canonicalIp((string) $allocation['ip']) ) ->unique() ->values() @@ -304,12 +302,11 @@ private function buildLocationAvailability( ], array_filter( $inventoryAllocations, - fn (array $allocation): bool => - ! in_array( - (int) $allocation['id'], - $blockedAllocationIds, - true - ) + fn (array $allocation): bool => ! in_array( + (int) $allocation['id'], + $blockedAllocationIds, + true + ) && ! in_array( $this->canonicalIp((string) $allocation['ip']), $nodeClaims['blocked_ips'], @@ -570,11 +567,10 @@ private function cpuPolicies(array $nodes): array /** * @param list $nodeIds - * Confirmed commitments remain in the local overlay until the independently - * read server snapshot proves the exact target vector. This closes the - * handoff window where the local row is consumed before every Pterodactyl - * inventory endpoint reflects the create or update. - * + * Confirmed commitments remain in the local overlay until the independently + * read server snapshot proves the exact target vector. This closes the + * handoff window where the local row is consumed before every Pterodactyl + * inventory endpoint reflects the create or update. * @param array>> $servers * @return array */ @@ -1039,13 +1035,11 @@ private function reservedAllocationClaims( $reservation = $reservationRows->first(); $claims = $reservationRows ->filter( - fn (object $row): bool => - $row->claim_row_id !== null + fn (object $row): bool => $row->claim_row_id !== null ) ->map(fn (object $row): object => (object) [ 'reservation_id' => (int) $row->reservation_id, - 'panel_identity' => - (string) $row->claim_panel_identity, + 'panel_identity' => (string) $row->claim_panel_identity, 'node_id' => (int) $row->claim_node_id, 'allocation_id' => (int) $row->allocation_id, 'ip' => $row->ip, @@ -1083,48 +1077,28 @@ private function reservedAllocationClaims( $this->upgradeIntegrity->verifiedSnapshot( (object) [ 'id' => $reservation->upgrade_id, - 'service_id' => - $reservation->upgrade_service_id, - 'product_id' => - $reservation->upgrade_product_id, - 'plan_id' => - $reservation->upgrade_plan_id, - 'invoice_id' => - $reservation->upgrade_invoice_id, + 'service_id' => $reservation->upgrade_service_id, + 'product_id' => $reservation->upgrade_product_id, + 'plan_id' => $reservation->upgrade_plan_id, + 'invoice_id' => $reservation->upgrade_invoice_id, 'status' => $reservation->upgrade_status, - 'active_service_guard_id' => - $reservation - ->upgrade_active_service_guard_id, - 'source_snapshot' => - $reservation->upgrade_source_snapshot, - 'target_snapshot' => - $reservation->upgrade_target_snapshot, - 'source_fingerprint' => - $reservation->upgrade_source_fingerprint, - 'target_fingerprint' => - $reservation->upgrade_target_fingerprint, - 'quoted_amount' => - $reservation->upgrade_quoted_amount, - 'currency_code' => - $reservation->upgrade_currency_code, - 'service_user_id' => - $reservation->service_user_id, - 'service_product_id' => - $reservation->service_product_id, - 'service_plan_id' => - $reservation->service_plan_id, - 'service_quantity' => - $reservation->service_quantity, - 'service_currency_code' => - $reservation->service_currency_code, - 'product_server_id' => - $reservation->upgrade_product_server_id, - 'invoice_status' => - $reservation->upgrade_invoice_status, - 'invoice_user_id' => - $reservation->upgrade_invoice_user_id, - 'invoice_currency_code' => - $reservation->upgrade_invoice_currency_code, + 'active_service_guard_id' => $reservation + ->upgrade_active_service_guard_id, + 'source_snapshot' => $reservation->upgrade_source_snapshot, + 'target_snapshot' => $reservation->upgrade_target_snapshot, + 'source_fingerprint' => $reservation->upgrade_source_fingerprint, + 'target_fingerprint' => $reservation->upgrade_target_fingerprint, + 'quoted_amount' => $reservation->upgrade_quoted_amount, + 'currency_code' => $reservation->upgrade_currency_code, + 'service_user_id' => $reservation->service_user_id, + 'service_product_id' => $reservation->service_product_id, + 'service_plan_id' => $reservation->service_plan_id, + 'service_quantity' => $reservation->service_quantity, + 'service_currency_code' => $reservation->service_currency_code, + 'product_server_id' => $reservation->upgrade_product_server_id, + 'invoice_status' => $reservation->upgrade_invoice_status, + 'invoice_user_id' => $reservation->upgrade_invoice_user_id, + 'invoice_currency_code' => $reservation->upgrade_invoice_currency_code, ], $reservation ); diff --git a/Services/ResourceQuoteService.php b/Services/ResourceQuoteService.php index c78c0b2..de2e806 100644 --- a/Services/ResourceQuoteService.php +++ b/Services/ResourceQuoteService.php @@ -12,8 +12,7 @@ public function __construct( private readonly ProductResourceConfigurationService $configuration, private readonly ResourceCalculationService $resources, private readonly AllocationSelectionService $allocations - ) { - } + ) {} /** * Return customer-safe, complete-vector slider bounds. No node identity or diff --git a/Services/SchedulerHealthService.php b/Services/SchedulerHealthService.php new file mode 100644 index 0000000..3301c88 --- /dev/null +++ b/Services/SchedulerHealthService.php @@ -0,0 +1,520 @@ + + */ + public static function taskDefinitions(): array + { + return [ + self::TASK_EXPIRE_CHECKOUT => [ + 'expected_interval_seconds' => 60, + 'lag_threshold_seconds' => 300, + ], + self::TASK_EXPIRE_UPGRADES => [ + 'expected_interval_seconds' => 60, + 'lag_threshold_seconds' => 300, + ], + self::TASK_RECONCILE_CHECKOUT => [ + 'expected_interval_seconds' => 600, + 'lag_threshold_seconds' => 1800, + ], + self::TASK_RECONCILE_UPGRADES => [ + 'expected_interval_seconds' => 600, + 'lag_threshold_seconds' => 1800, + ], + self::TASK_CAPACITY_ALERTS => [ + 'expected_interval_seconds' => 300, + 'lag_threshold_seconds' => 900, + ], + ]; + } + + /** + * Run one independently scheduled task and persist whether the entire + * invocation was healthy. A partial run never refreshes last_succeeded_at. + */ + public function run(string $taskName, callable $task): int + { + $this->startRun($taskName); + $processed = 0; + + try { + $result = $task(); + $processed = is_int($result) ? $result : 0; + } catch (\Throwable $exception) { + $this->recordFailure($taskName, [ + 'kind' => 'task_failure', + 'task' => $taskName, + 'entity_type' => 'scheduler_task', + 'entity_id' => $taskName, + 'exception' => $exception::class, + 'error' => $exception->getMessage(), + 'failed_at' => now()->toIso8601String(), + ], $exception); + $this->finishRun($taskName, $processed); + + throw $exception; + } + + $this->finishRun($taskName, $processed); + + return $processed; + } + + /** + * Process a bounded set of database identities without allowing one bad + * row to suppress later work. + */ + public function processRows( + string $taskName, + string $entityType, + iterable $entityIds, + callable $processor, + ): int { + $processed = 0; + + foreach ($entityIds as $entityId) { + try { + if ($processor($entityId)) { + $processed++; + } + } catch (\Throwable $exception) { + $this->recordRowFailure( + $taskName, + $entityType, + is_numeric($entityId) ? (int) $entityId : (string) $entityId, + $exception + ); + } + } + + return $processed; + } + + /** + * Select and process one fair, bounded cycle segment. The persisted cursor + * advances before every row attempt, so a deterministic failure cannot pin + * the first page forever. A short forward page wraps to the lowest eligible + * identities and eventually retries repaired rows. + * + * @param callable(): (EloquentBuilder|QueryBuilder) $eligibleQuery + */ + public function processEligibleRows( + string $taskName, + string $entityType, + int $limit, + callable $eligibleQuery, + callable $processor, + ): int { + $limit = max(1, $limit); + $this->ensureTask($taskName); + $cursor = (int) DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $taskName) + ->value('last_scanned_entity_id'); + $baseQuery = $eligibleQuery(); + if ( + ! $baseQuery instanceof EloquentBuilder + && ! $baseQuery instanceof QueryBuilder + ) { + throw new \InvalidArgumentException( + 'The scheduler eligible-query factory must return a database query builder.' + ); + } + + $entityIds = (clone $baseQuery) + ->where('id', '>', $cursor) + ->reorder() + ->orderBy('id') + ->limit($limit) + ->pluck('id') + ->map(fn ($entityId): int => (int) $entityId) + ->values(); + $remaining = $limit - $entityIds->count(); + if ($remaining > 0 && $cursor > 0) { + $wrappedIds = (clone $baseQuery) + ->where('id', '<=', $cursor) + ->reorder() + ->orderBy('id') + ->limit($remaining) + ->pluck('id') + ->map(fn ($entityId): int => (int) $entityId); + $entityIds = $entityIds + ->concat($wrappedIds) + ->values(); + } + + return $this->processRows( + $taskName, + $entityType, + $entityIds, + function (int $entityId) use ( + $taskName, + $processor + ): bool { + DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $taskName) + ->update([ + 'last_scanned_entity_id' => $entityId, + 'updated_at' => now(), + ]); + + return $processor($entityId); + } + ); + } + + public function recordRowFailure( + string $taskName, + string $entityType, + int|string $entityId, + \Throwable $exception, + ): void { + $this->recordFailure($taskName, [ + 'kind' => 'row_failure', + 'task' => $taskName, + 'entity_type' => $entityType, + 'entity_id' => $entityId, + 'exception' => $exception::class, + 'error' => $exception->getMessage(), + 'failed_at' => now()->toIso8601String(), + ], $exception); + } + + /** + * Persist and alert for tasks that have not completed one fully healthy + * run within their configured threshold. + */ + public function checkForLag(): int + { + $lagging = 0; + + foreach (self::taskDefinitions() as $taskName => $definition) { + $context = null; + try { + $this->ensureTask($taskName); + $context = DB::transaction(function () use ( + $taskName, + $definition + ): ?array { + $heartbeat = DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $taskName) + ->lockForUpdate() + ->first(); + if ($heartbeat === null) { + return null; + } + + $reference = $heartbeat->last_succeeded_at + ?? $heartbeat->created_at; + $lagSeconds = max( + 0, + now()->getTimestamp() + - Carbon::parse($reference)->getTimestamp() + ); + $isLagging = $lagSeconds + > (int) $definition['lag_threshold_seconds']; + $shouldAlert = $isLagging + && ( + $heartbeat->last_alerted_at === null + || Carbon::parse($heartbeat->last_alerted_at) + ->lte(now()->subMinutes( + self::ALERT_COOLDOWN_MINUTES + )) + ); + + DB::table('ptero_scheduler_heartbeats') + ->where('id', $heartbeat->id) + ->update([ + 'last_lag_checked_at' => now(), + 'lag_detected_at' => $isLagging + ? ($heartbeat->lag_detected_at ?? now()) + : null, + 'last_alerted_at' => $shouldAlert + ? now() + : $heartbeat->last_alerted_at, + 'updated_at' => now(), + ]); + + if (! $isLagging) { + return null; + } + + return [ + 'kind' => 'scheduler_lag', + 'task' => $taskName, + 'lag_seconds' => $lagSeconds, + 'lag_threshold_seconds' => (int) $definition[ + 'lag_threshold_seconds' + ], + 'last_succeeded_at' => $heartbeat->last_succeeded_at, + 'error' => 'No fully successful run completed within the scheduler lag threshold.', + 'should_alert' => $shouldAlert, + ]; + }, 5); + } catch (\Throwable $exception) { + $this->safeLog('error', 'Scheduler heartbeat lag check failed', [ + 'task' => $taskName, + 'error' => $exception->getMessage(), + ]); + $this->reportThrowable($exception); + } + + if ($context === null) { + continue; + } + + $lagging++; + if ($context['should_alert']) { + unset($context['should_alert']); + $this->safeLog( + 'warning', + 'Dynamic Pterodactyl scheduled task is lagging', + $context + ); + $this->notifyOperators($context); + } + } + + return $lagging; + } + + private function startRun(string $taskName): void + { + try { + $this->ensureTask($taskName); + DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $taskName) + ->update([ + 'last_started_at' => now(), + 'last_failure_count' => 0, + 'updated_at' => now(), + ]); + } catch (\Throwable $exception) { + $this->safeLog('error', 'Scheduler heartbeat start write failed', [ + 'task' => $taskName, + 'error' => $exception->getMessage(), + ]); + $this->reportThrowable($exception); + } + } + + private function finishRun(string $taskName, int $processed): void + { + try { + DB::transaction(function () use ($taskName, $processed): void { + $heartbeat = DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $taskName) + ->lockForUpdate() + ->first(); + if ($heartbeat === null) { + return; + } + + $healthy = (int) $heartbeat->last_failure_count === 0; + $updates = [ + 'last_completed_at' => now(), + 'last_processed_count' => max(0, $processed), + 'consecutive_failures' => $healthy + ? 0 + : ((int) $heartbeat->consecutive_failures + 1), + 'updated_at' => now(), + ]; + if ($healthy) { + $updates += [ + 'last_succeeded_at' => now(), + 'lag_detected_at' => null, + 'last_error' => null, + 'last_failure_context' => null, + ]; + } + + DB::table('ptero_scheduler_heartbeats') + ->where('id', $heartbeat->id) + ->update($updates); + }, 5); + } catch (\Throwable $exception) { + $this->safeLog('error', 'Scheduler heartbeat completion write failed', [ + 'task' => $taskName, + 'error' => $exception->getMessage(), + ]); + $this->reportThrowable($exception); + } + } + + /** + * @param array $context + */ + private function recordFailure( + string $taskName, + array $context, + \Throwable $exception, + ): void { + $this->safeLog( + 'error', + 'Dynamic Pterodactyl scheduled work failed', + $context + ); + $this->reportThrowable($exception); + + $shouldAlert = false; + try { + $this->ensureTask($taskName); + $shouldAlert = DB::transaction(function () use ( + $taskName, + $context + ): bool { + $heartbeat = DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $taskName) + ->lockForUpdate() + ->first(); + if ($heartbeat === null) { + return false; + } + + $shouldAlert = $heartbeat->last_alerted_at === null + || Carbon::parse($heartbeat->last_alerted_at) + ->lte(now()->subMinutes( + self::ALERT_COOLDOWN_MINUTES + )); + + DB::table('ptero_scheduler_heartbeats') + ->where('id', $heartbeat->id) + ->update([ + 'last_failed_at' => now(), + 'last_failure_count' => DB::raw( + 'last_failure_count + 1' + ), + 'last_error' => substr( + (string) ($context['error'] ?? ''), + 0, + 4000 + ), + 'last_failure_context' => json_encode( + $context, + JSON_THROW_ON_ERROR + | JSON_INVALID_UTF8_SUBSTITUTE + ), + 'last_alerted_at' => $shouldAlert + ? now() + : $heartbeat->last_alerted_at, + 'updated_at' => now(), + ]); + + return $shouldAlert; + }, 5); + } catch (\Throwable $heartbeatException) { + $this->safeLog('error', 'Scheduler failure heartbeat write failed', [ + 'task' => $taskName, + 'entity_type' => $context['entity_type'] ?? null, + 'entity_id' => $context['entity_id'] ?? null, + 'error' => $heartbeatException->getMessage(), + ]); + $this->reportThrowable($heartbeatException); + } + + if ($shouldAlert) { + $this->notifyOperators($context); + } + } + + private function ensureTask(string $taskName): void + { + $definition = self::taskDefinitions()[$taskName] ?? [ + 'expected_interval_seconds' => 300, + 'lag_threshold_seconds' => 900, + ]; + $now = now(); + + DB::table('ptero_scheduler_heartbeats')->upsert([[ + 'task_name' => $taskName, + 'expected_interval_seconds' => $definition[ + 'expected_interval_seconds' + ], + 'lag_threshold_seconds' => $definition[ + 'lag_threshold_seconds' + ], + 'created_at' => $now, + 'updated_at' => $now, + ]], ['task_name'], [ + 'expected_interval_seconds', + 'lag_threshold_seconds', + 'updated_at', + ]); + } + + /** + * @param array $context + */ + private function notifyOperators(array $context): void + { + try { + $this->operatorAlerts->notify($context); + } catch (\Throwable $exception) { + $this->safeLog( + 'critical', + 'Scheduler failure operator alert could not be delivered', + [ + 'task' => $context['task'] ?? null, + 'entity_type' => $context['entity_type'] ?? null, + 'entity_id' => $context['entity_id'] ?? null, + 'error' => $exception->getMessage(), + ] + ); + $this->reportThrowable($exception); + } + } + + /** + * @param array $context + */ + private function safeLog( + string $level, + string $message, + array $context, + ): void { + try { + Log::{$level}($message, $context); + } catch (\Throwable) { + // Plain unit tests may not boot Laravel's logging facade. + } + } + + private function reportThrowable(\Throwable $throwable): void + { + try { + app(ExceptionHandler::class)->report($throwable); + } catch (\Throwable) { + // Heartbeat reporting must never suppress later lifecycle rows. + } + } +} diff --git a/Services/SchedulerOperatorAlertService.php b/Services/SchedulerOperatorAlertService.php new file mode 100644 index 0000000..13acbc5 --- /dev/null +++ b/Services/SchedulerOperatorAlertService.php @@ -0,0 +1,85 @@ + $context + */ + public function notify(array $context): void + { + try { + $recipients = User::whereNotNull('role_id')->get(); + } catch (\Throwable $exception) { + $this->safeLog( + 'critical', + 'Scheduler failure recipients could not be loaded', + $context + ['notification_error' => $exception->getMessage()] + ); + $this->reportThrowable($exception); + + return; + } + + if ($recipients->isEmpty()) { + $this->safeLog( + 'critical', + 'Dynamic Pterodactyl scheduler requires attention', + $context + ); + + return; + } + + foreach ($recipients as $recipient) { + try { + $recipient->notify( + new SchedulerTaskFailureNotification($context) + ); + } catch (\Throwable $exception) { + $this->safeLog( + 'error', + 'Failed to notify operator about scheduler health', + [ + 'task' => $context['task'] ?? null, + 'entity_type' => $context['entity_type'] ?? null, + 'entity_id' => $context['entity_id'] ?? null, + 'recipient_id' => $recipient->id ?? null, + 'error' => $exception->getMessage(), + ] + ); + $this->reportThrowable($exception); + } + } + } + + /** + * @param array $context + */ + private function safeLog( + string $level, + string $message, + array $context, + ): void { + try { + Log::{$level}($message, $context); + } catch (\Throwable) { + // Scheduler alerting must not interrupt later lifecycle rows. + } + } + + private function reportThrowable(\Throwable $throwable): void + { + try { + app(ExceptionHandler::class)->report($throwable); + } catch (\Throwable) { + // The application exception handler may itself be unavailable. + } + } +} diff --git a/Services/UpgradeReservationIntegrityService.php b/Services/UpgradeReservationIntegrityService.php index 1d3f077..4080740 100644 --- a/Services/UpgradeReservationIntegrityService.php +++ b/Services/UpgradeReservationIntegrityService.php @@ -25,21 +25,15 @@ public function fingerprint(object $upgrade, array $context): string return hash('sha256', json_encode( $this->canonicalizeSnapshot([ 'upgrade_id' => (int) $upgrade->id, - 'source_fingerprint' => - (string) $upgrade->source_fingerprint, - 'target_fingerprint' => - (string) $upgrade->target_fingerprint, + 'source_fingerprint' => (string) $upgrade->source_fingerprint, + 'target_fingerprint' => (string) $upgrade->target_fingerprint, 'panel_identity' => $context['panel_identity'], 'node_id' => $context['node_id'], 'location_id' => $context['location_id'], - 'external_server_id' => - $context['external_server_id'], - 'external_server_uuid' => - $context['external_server_uuid'], - 'external_server_identifier' => - $context['external_server_identifier'], - 'external_server_external_id' => - $context['external_server_external_id'], + 'external_server_id' => $context['external_server_id'], + 'external_server_uuid' => $context['external_server_uuid'], + 'external_server_identifier' => $context['external_server_identifier'], + 'external_server_external_id' => $context['external_server_external_id'], 'external_user_id' => $context['external_user_id'], 'user_external_id' => $context['user_external_id'], 'user_email' => $context['user_email'], @@ -47,16 +41,14 @@ public function fingerprint(object $upgrade, array $context): string 'egg_id' => $context['egg_id'], 'preserved_build' => $context['preserved_build'], 'allocation_id' => $context['allocation_id'], - 'assigned_allocation_ids' => - $context['assigned_allocation_ids'], + 'assigned_allocation_ids' => $context['assigned_allocation_ids'], 'source' => $context['source'], 'target' => $context['target'], 'delta' => $context['delta'], 'quoted_amount' => $this->normalizedMoney( $upgrade->quoted_amount ), - 'currency_code' => - strtoupper((string) $upgrade->currency_code), + 'currency_code' => strtoupper((string) $upgrade->currency_code), ]), JSON_THROW_ON_ERROR | JSON_PRESERVE_ZERO_FRACTION @@ -70,8 +62,7 @@ public function pricingVersion(object $upgrade): string 'quoted_amount' => $this->normalizedMoney( $upgrade->quoted_amount ), - 'currency_code' => - strtoupper((string) $upgrade->currency_code), + 'currency_code' => strtoupper((string) $upgrade->currency_code), ], JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES)); } @@ -852,6 +843,7 @@ private function lifecycleMatches( if ($reservationStatus !== 'confirmed' || $consumedAt === null) { return false; } + return $upgradeStatus === 'completed' && $reservationGuard === null && $upgradeGuard === null; diff --git a/Services/UpgradeReservationService.php b/Services/UpgradeReservationService.php index 25a1641..baa7311 100644 --- a/Services/UpgradeReservationService.php +++ b/Services/UpgradeReservationService.php @@ -5,13 +5,15 @@ use App\Exceptions\DisplayException; use App\Exceptions\PermanentProvisioningException; use App\Helpers\ExtensionHelper; -use App\Jobs\Server\UpgradeJob; use App\Models\Invoice; use App\Models\Service; use App\Models\ServiceUpgrade; use App\Services\Invoice\CancelInvoiceService; use App\Services\Invoice\CapacityInvoicePaymentService; +use App\Services\Service\CapacityConfigurationLockService; use App\Services\ServiceUpgrade\CapacityUpgradeReservationIdentity; +use App\Services\ServiceUpgrade\ServiceUpgradeDispatchRecoveryService; +use App\Services\ServiceUpgrade\ServiceUpgradeMutationCoordinator; use App\Services\ServiceUpgrade\ServiceUpgradeService; use App\Support\PanelEndpointIdentity; use App\Support\StrictInteger; @@ -115,10 +117,8 @@ public function reserveForUpgrade( 'location_id' => $context['location_id'], 'external_server_id' => $context['external_server_id'], 'external_server_uuid' => $context['external_server_uuid'], - 'external_server_identifier' => - $context['external_server_identifier'], - 'external_server_external_id' => - $context['external_server_external_id'], + 'external_server_identifier' => $context['external_server_identifier'], + 'external_server_external_id' => $context['external_server_external_id'], 'external_user_id' => $context['external_user_id'], 'user_external_id' => $context['user_external_id'], 'user_email' => $context['user_email'], @@ -126,8 +126,7 @@ public function reserveForUpgrade( 'egg_id' => $context['egg_id'], 'preserved_build' => $context['preserved_build'], 'allocation_id' => $context['allocation_id'], - 'assigned_allocation_ids' => - $context['assigned_allocation_ids'], + 'assigned_allocation_ids' => $context['assigned_allocation_ids'], 'source' => $context['source'], 'target' => $context['target'], 'delta' => $context['delta'], @@ -156,8 +155,7 @@ public function reserveForUpgrade( 'currency_code' => strtoupper((string) $upgrade->currency_code), 'configuration_fingerprint' => $fingerprint, 'configuration_payload' => $payload, - 'pricing_version' => - $this->integrity->pricingVersion($upgrade), + 'pricing_version' => $this->integrity->pricingVersion($upgrade), 'formula_version' => 'dynamic-upgrade-v1', // Full target values are provisioning truth. 'memory' => $context['target']['memory'], @@ -171,8 +169,7 @@ public function reserveForUpgrade( 'external_server_id' => $context['external_server_id'], 'external_user_id' => $context['external_user_id'], 'external_server_uuid' => $context['external_server_uuid'], - 'external_server_identifier' => - $context['external_server_identifier'], + 'external_server_identifier' => $context['external_server_identifier'], 'pricing_breakdown' => [ 'kind' => 'resource_upgrade', 'source' => $context['source'], @@ -409,7 +406,8 @@ public function preflightPaidUpgrade( ? "{$reason} External payment evidence exists; refund or account-credit review is required." : $reason, 'failed_at' => now(), - ])->save(); + ]); + ServiceUpgradeMutationCoordinator::save($lockedUpgrade); if ($reservation !== null && $reservation->status === 'pending') { $reservation->forceFill([ 'status' => $reservation->guaranteed_until?->isPast() @@ -433,164 +431,177 @@ public function preflightPaidUpgrade( public function expireUnpaidUpgrades(int $limit = 100): int { - $candidateIds = UpgradeReservation::query() - ->where('purpose', 'upgrade') - ->where('status', 'pending') - ->where('guaranteed_until', '<=', now()) - ->orderBy('id') - ->limit($limit) - ->pluck('id'); - $expired = 0; - - foreach ($candidateIds as $reservationId) { - $didExpire = DB::transaction(function () use ($reservationId): bool { - $candidate = UpgradeReservation::query()->find($reservationId); - if ($candidate === null) { - return false; - } + $limit = max(1, min($limit, 500)); - $invoice = $candidate->invoice_id !== null - ? Invoice::query() - ->whereKey($candidate->invoice_id) + return app(SchedulerHealthService::class)->processEligibleRows( + SchedulerHealthService::TASK_EXPIRE_UPGRADES, + 'resource_reservation', + $limit, + fn () => UpgradeReservation::query() + ->where('purpose', 'upgrade') + ->where('status', 'pending') + ->where('guaranteed_until', '<=', now()), + function (int $reservationId): bool { + return DB::transaction(function () use ( + $reservationId + ): bool { + $candidate = UpgradeReservation::query() + ->find($reservationId); + if ($candidate === null) { + return false; + } + + $invoice = $candidate->invoice_id !== null + ? Invoice::query() + ->whereKey($candidate->invoice_id) + ->lockForUpdate() + ->first() + : null; + $serviceId = ServiceUpgrade::query() + ->whereKey($candidate->service_upgrade_id) + ->value('service_id'); + if ($serviceId !== null) { + Service::query() + ->whereKey($serviceId) + ->lockForUpdate() + ->firstOrFail(); + } + $upgrade = ServiceUpgrade::query() + ->whereKey($candidate->service_upgrade_id) ->lockForUpdate() - ->first() - : null; - $serviceId = ServiceUpgrade::query() - ->whereKey($candidate->service_upgrade_id) - ->value('service_id'); - if ($serviceId !== null) { - Service::query() - ->whereKey($serviceId) + ->first(); + $reservation = UpgradeReservation::query() + ->whereKey($reservationId) ->lockForUpdate() - ->firstOrFail(); - } - $upgrade = ServiceUpgrade::query() - ->whereKey($candidate->service_upgrade_id) - ->lockForUpdate() - ->first(); - $reservation = UpgradeReservation::query() - ->whereKey($reservationId) - ->lockForUpdate() - ->first(); - if ($invoice !== null) { - $invoice->items() - ->orderBy('id') - ->lockForUpdate() - ->get(); - } - - if ( - $reservation === null - || $reservation->status !== 'pending' - || $reservation->guaranteed_until?->isFuture() - || $invoice?->status === Invoice::STATUS_PAID - ) { - return false; - } - - $reason = 'The unpaid upgrade capacity guarantee expired.'; - $paymentAttention = $invoice !== null - && $invoice->status === Invoice::STATUS_PENDING - && app(CapacityInvoicePaymentService::class) - ->hasInFlightOrSucceededPayment($invoice); - $reservation->forceFill([ - 'status' => 'expired', - 'upgrade_guard_id' => null, - 'admin_notes' => $reason, - ])->save(); - if ($upgrade !== null && in_array($upgrade->status, [ - ServiceUpgrade::STATUS_PENDING, - ServiceUpgrade::STATUS_AWAITING_PAYMENT, - ], true)) { - $upgrade->forceFill([ - 'status' => $paymentAttention - ? ServiceUpgrade::STATUS_NEEDS_ATTENTION - : ServiceUpgrade::STATUS_CANCELLED, - 'active_service_guard_id' => $paymentAttention - ? $upgrade->service_id - : null, - 'last_error' => $paymentAttention - ? 'The capacity guarantee expired with payment activity; refund or account-credit review is required.' - : $reason, - 'failed_at' => now(), + ->first(); + if ($invoice !== null) { + $invoice->items() + ->orderBy('id') + ->lockForUpdate() + ->get(); + } + + if ( + $reservation === null + || $reservation->status !== 'pending' + || $reservation->guaranteed_until?->isFuture() + || $invoice?->status === Invoice::STATUS_PAID + ) { + return false; + } + + $reason = 'The unpaid upgrade capacity guarantee expired.'; + $paymentAttention = $invoice !== null + && $invoice->status === Invoice::STATUS_PENDING + && app(CapacityInvoicePaymentService::class) + ->hasInFlightOrSucceededPayment($invoice); + $reservation->forceFill([ + 'status' => 'expired', + 'upgrade_guard_id' => null, + 'admin_notes' => $reason, ])->save(); - } - if ($paymentAttention) { - app(CapacityInvoicePaymentService::class)->requireAttention( - $invoice, - 'The seven-day upgrade capacity guarantee expired after a partial or in-flight payment. Capacity was released; refund or account-credit review is required.' - ); - } elseif ($invoice?->status === Invoice::STATUS_PENDING) { - app(CancelInvoiceService::class) - ->markCancelledAfterFulfillment($invoice); - } - - return true; - }, 5); - - $expired += $didExpire ? 1 : 0; - } - - return $expired; + if ($upgrade !== null && in_array($upgrade->status, [ + ServiceUpgrade::STATUS_PENDING, + ServiceUpgrade::STATUS_AWAITING_PAYMENT, + ], true)) { + $upgrade->forceFill([ + 'status' => $paymentAttention + ? ServiceUpgrade::STATUS_NEEDS_ATTENTION + : ServiceUpgrade::STATUS_CANCELLED, + 'active_service_guard_id' => $paymentAttention + ? $upgrade->service_id + : null, + 'last_error' => $paymentAttention + ? 'The capacity guarantee expired with payment activity; refund or account-credit review is required.' + : $reason, + 'failed_at' => now(), + ]); + ServiceUpgradeMutationCoordinator::save($upgrade); + } + if ($paymentAttention) { + app(CapacityInvoicePaymentService::class) + ->requireAttention( + $invoice, + 'The seven-day upgrade capacity guarantee expired after a partial or in-flight payment. Capacity was released; refund or account-credit review is required.' + ); + } elseif ( + $invoice?->status === Invoice::STATUS_PENDING + ) { + app(CancelInvoiceService::class) + ->markCancelledAfterFulfillment($invoice); + } + + return true; + }, 5); + } + ); } public function reconcileStalledUpgrades(int $limit = 100): int { - $upgradeIds = ServiceUpgrade::query() - ->where('status', ServiceUpgrade::STATUS_PROVISIONING) - ->where('provisioning_started_at', '<=', now()->subMinutes(10)) - ->orderBy('id') - ->limit($limit) - ->pluck('id'); - $requeued = 0; - - foreach ($upgradeIds as $upgradeId) { - $didRequeue = DB::transaction(function () use ($upgradeId): bool { - $upgrade = ServiceUpgrade::query() - ->whereKey($upgradeId) - ->lockForUpdate() - ->first(); - $reservation = UpgradeReservation::query() - ->where('purpose', 'upgrade') - ->where('service_upgrade_id', $upgradeId) - ->lockForUpdate() - ->first(); - - if ( - $upgrade === null - || $reservation === null - || $upgrade->status !== ServiceUpgrade::STATUS_PROVISIONING - || $upgrade->provisioning_started_at?->isAfter(now()->subMinutes(10)) - || $reservation->status !== 'paid_committed' - ) { - return false; - } - - $message = 'A stale upgrade worker lease was recovered for retry.'; - $reservation->forceFill([ - 'provisioning_lease_id' => null, - 'provisioning_started_at' => null, - 'last_provisioning_error' => $message, - ])->save(); - $upgrade->forceFill([ - 'status' => ServiceUpgrade::STATUS_RETRYABLE_FAILED, - 'last_error' => $message, - 'failed_at' => now(), - ])->save(); - - DB::afterCommit( - fn () => UpgradeJob::dispatch( - ServiceUpgrade::query()->findOrFail($upgradeId) - ) - ); - - return true; - }, 5); + $limit = max(1, min($limit, 500)); + + return app(SchedulerHealthService::class)->processEligibleRows( + SchedulerHealthService::TASK_RECONCILE_UPGRADES, + 'service_upgrade', + $limit, + fn () => ServiceUpgrade::query() + ->where('status', ServiceUpgrade::STATUS_PROVISIONING) + ->where( + 'provisioning_started_at', + '<=', + now()->subMinutes(10) + ), + function (int $upgradeId): bool { + return DB::transaction(function () use ( + $upgradeId + ): bool { + $upgrade = ServiceUpgrade::query() + ->whereKey($upgradeId) + ->lockForUpdate() + ->first(); + $reservation = UpgradeReservation::query() + ->where('purpose', 'upgrade') + ->where('service_upgrade_id', $upgradeId) + ->lockForUpdate() + ->first(); + + if ( + $upgrade === null + || $reservation === null + || $upgrade->status + !== ServiceUpgrade::STATUS_PROVISIONING + || $upgrade->provisioning_started_at?->isAfter( + now()->subMinutes(10) + ) + || $reservation->status !== 'paid_committed' + ) { + return false; + } + + $message = 'A stale upgrade worker lease was recovered for retry.'; + $reservation->forceFill([ + 'provisioning_lease_id' => null, + 'provisioning_started_at' => null, + 'last_provisioning_error' => $message, + ])->save(); + $upgrade->forceFill([ + 'status' => ServiceUpgrade::STATUS_RETRYABLE_FAILED, + 'last_error' => $message, + 'failed_at' => now(), + ]); + ServiceUpgradeMutationCoordinator::save($upgrade); - $requeued += $didRequeue ? 1 : 0; - } + DB::afterCommit( + fn () => app( + ServiceUpgradeDispatchRecoveryService::class + )->dispatchById($upgradeId) + ); - return $requeued; + return true; + }, 5); + } + ); } /** @@ -671,16 +682,11 @@ public function beginProvisioning(ServiceUpgrade $upgrade): array 'source' => (array) ($payload['source'] ?? []), 'target' => (array) ($payload['target'] ?? []), 'external_server_id' => (int) ($payload['external_server_id'] ?? 0), - 'external_server_uuid' => - (string) ($payload['external_server_uuid'] ?? ''), - 'external_server_identifier' => - (string) ($payload['external_server_identifier'] ?? ''), - 'external_server_external_id' => - (string) ($payload['external_server_external_id'] ?? ''), - 'external_user_id' => - (int) ($payload['external_user_id'] ?? 0), - 'user_external_id' => - (string) ($payload['user_external_id'] ?? ''), + 'external_server_uuid' => (string) ($payload['external_server_uuid'] ?? ''), + 'external_server_identifier' => (string) ($payload['external_server_identifier'] ?? ''), + 'external_server_external_id' => (string) ($payload['external_server_external_id'] ?? ''), + 'external_user_id' => (int) ($payload['external_user_id'] ?? 0), + 'user_external_id' => (string) ($payload['user_external_id'] ?? ''), 'user_email' => (string) ($payload['user_email'] ?? ''), 'nest_id' => (int) ($payload['nest_id'] ?? 0), 'egg_id' => (int) ($payload['egg_id'] ?? 0), @@ -830,7 +836,7 @@ public function quoteForService(Service $service, array $submittedOptions): arra } $lockedProduct = app( - \App\Services\Service\CapacityConfigurationLockService::class + CapacityConfigurationLockService::class )->lockProduct((int) $service->product_id); $service->setRelation('product', $lockedProduct); $this->inventory->assertExclusiveProvisioningControl(); @@ -1074,10 +1080,8 @@ private function upgradeContext( 'location_id' => (int) $node['location_id'], 'external_server_id' => $checkoutIdentity['id'], 'external_server_uuid' => $checkoutIdentity['uuid'], - 'external_server_identifier' => - $checkoutIdentity['identifier'], - 'external_server_external_id' => - (string) $upgrade->service_id, + 'external_server_identifier' => $checkoutIdentity['identifier'], + 'external_server_external_id' => (string) $upgrade->service_id, 'external_user_id' => $checkoutIdentity['external_user_id'], 'user_external_id' => $checkoutIdentity['user_external_id'], 'user_email' => $checkoutIdentity['user_email'], diff --git a/database/migrations/2026_07_25_000002_normalize_dynamic_option_keys.php b/database/migrations/2026_07_25_000002_normalize_dynamic_option_keys.php index ab60729..69c0b8f 100644 --- a/database/migrations/2026_07_25_000002_normalize_dynamic_option_keys.php +++ b/database/migrations/2026_07_25_000002_normalize_dynamic_option_keys.php @@ -1,14 +1,19 @@ join( 'config_option_products', @@ -16,44 +21,113 @@ public function up(): void '=', 'config_options.id' ) - ->join('products', 'products.id', '=', 'config_option_products.product_id') - ->join('extensions', 'extensions.id', '=', 'products.server_id') + ->join( + 'products', + 'products.id', + '=', + 'config_option_products.product_id' + ) + ->join( + 'extensions', + 'extensions.id', + '=', + 'products.server_id' + ) ->where('extensions.type', 'server') ->where('extensions.extension', 'Pterodactyl') ->whereNull('config_options.parent_id') - ->whereIn('config_options.type', ['dynamic_slider', 'select']) + ->whereIn( + 'config_options.type', + ['dynamic_slider', 'select'] + ) ->distinct() ->pluck('config_options.id'); $options = DB::table('config_options') ->whereIn('id', $optionIds) - ->get(['id', 'name', 'type', 'env_variable', 'metadata']); + ->orderBy('id') + ->lockForUpdate() + ->get([ + 'id', + 'name', + 'type', + 'env_variable', + 'metadata', + ]); + $optionUpdates = []; + $serviceIdsByResource = [ + 'memory' => [], + 'cpu' => [], + 'disk' => [], + ]; foreach ($options as $option) { - $metadata = is_string($option->metadata) - ? json_decode($option->metadata, true) ?? [] - : (array) $option->metadata; - $resourceType = strtolower((string) ($metadata['resource_type'] ?? '')); + try { + $metadata = is_string($option->metadata) + ? json_decode( + $option->metadata, + true, + 512, + JSON_THROW_ON_ERROR + ) + : (array) $option->metadata; + } catch (JsonException $exception) { + throw new RuntimeException( + "Dynamic option {$option->id} has invalid metadata.", + previous: $exception + ); + } + if ( + $option->type === 'dynamic_slider' + && ( + ! is_array($metadata) + || array_is_list($metadata) + ) + ) { + throw new RuntimeException( + "Dynamic option {$option->id} has invalid metadata." + ); + } + $resourceType = strtolower( + (string) ($metadata['resource_type'] ?? '') + ); $isResource = $option->type === 'dynamic_slider' - && in_array($resourceType, ['memory', 'cpu', 'disk'], true); - $isLocation = strtolower((string) $option->name) === 'location'; + && array_key_exists( + $resourceType, + $serviceIdsByResource + ); + $isLocation = strtolower((string) $option->name) + === 'location'; if (! $isResource && ! $isLocation) { continue; } - $normalizedKey = $isResource ? $resourceType : 'location'; - DB::table('config_options') - ->where('id', $option->id) - ->update(['env_variable' => $normalizedKey]); + $normalizedKey = $isResource + ? $resourceType + : 'location'; + $optionUpdates[(int) $option->id] = $normalizedKey; if (! $isResource) { continue; } $productIds = DB::table('config_option_products') - ->join('products', 'products.id', '=', 'config_option_products.product_id') - ->join('extensions', 'extensions.id', '=', 'products.server_id') - ->where('config_option_products.config_option_id', $option->id) + ->join( + 'products', + 'products.id', + '=', + 'config_option_products.product_id' + ) + ->join( + 'extensions', + 'extensions.id', + '=', + 'products.server_id' + ) + ->where( + 'config_option_products.config_option_id', + $option->id + ) ->where('extensions.type', 'server') ->where('extensions.extension', 'Pterodactyl') ->pluck('config_option_products.product_id'); @@ -62,37 +136,173 @@ public function up(): void ->pluck('id'); foreach ($serviceIds as $serviceId) { - $upper = DB::table('properties') - ->where('model_type', Service::class) - ->where('model_id', $serviceId) - ->where('key', strtoupper($normalizedKey)) - ->first(); - - if ($upper === null) { - continue; - } + $serviceIdsByResource[$normalizedKey][ + (int) $serviceId + ] = true; + } + } + + $propertyMutations = $this->preflightPropertyMutations( + $serviceIdsByResource + ); + + foreach ($optionUpdates as $optionId => $normalizedKey) { + DB::table('config_options') + ->where('id', $optionId) + ->update(['env_variable' => $normalizedKey]); + } + + foreach ($propertyMutations as $mutation) { + if ($mutation['action'] === 'delete') { + DB::table('properties') + ->where('id', $mutation['id']) + ->delete(); + + continue; + } + + DB::table('properties') + ->where('id', $mutation['id']) + ->update(['key' => $mutation['key']]); + } + }); + } - $lowerExists = DB::table('properties') - ->where('model_type', Service::class) - ->where('model_id', $serviceId) - ->where('key', $normalizedKey) - ->exists(); + /** + * @param array> $serviceIdsByResource + * @return array + */ + private function preflightPropertyMutations( + array $serviceIdsByResource + ): array { + $allServiceIds = []; + foreach ($serviceIdsByResource as $serviceIds) { + foreach (array_keys($serviceIds) as $serviceId) { + $allServiceIds[$serviceId] = true; + } + } - if ($lowerExists) { - DB::table('properties')->where('id', $upper->id)->delete(); + if ($allServiceIds === []) { + return []; + } + + $propertiesByService = []; + $properties = DB::table('properties') + ->where('model_type', Service::class) + ->whereIn('model_id', array_keys($allServiceIds)) + ->orderBy('id') + ->lockForUpdate() + ->get(['id', 'model_id', 'key', 'value']); + + foreach ($properties as $property) { + $propertiesByService[(int) $property->model_id][] = + $property; + } + + $mutations = []; + foreach ($serviceIdsByResource as $normalizedKey => $serviceIds) { + foreach (array_keys($serviceIds) as $serviceId) { + $matching = array_values(array_filter( + $propertiesByService[$serviceId] ?? [], + static fn (object $property): bool => strtolower(trim((string) $property->key)) + === $normalizedKey + )); + + $lower = null; + $upper = null; + foreach ($matching as $property) { + $storedKey = (string) $property->key; + if ($storedKey === $normalizedKey) { + if ($lower !== null) { + throw new RuntimeException( + "Service {$serviceId} has duplicate " + ."[{$normalizedKey}] properties." + ); + } + $lower = $property; + } elseif ( + $storedKey === strtoupper($normalizedKey) + ) { + if ($upper !== null) { + throw new RuntimeException( + "Service {$serviceId} has duplicate " + ."[{$normalizedKey}] properties." + ); + } + $upper = $property; } else { - DB::table('properties') - ->where('id', $upper->id) - ->update(['key' => $normalizedKey]); + throw new RuntimeException( + "Service {$serviceId} has unsupported " + ."resource key casing [{$storedKey}]." + ); + } + } + + $lowerValue = $this->strictPropertyValue( + $lower, + $serviceId, + $normalizedKey + ); + $upperValue = $this->strictPropertyValue( + $upper, + $serviceId, + $normalizedKey + ); + + if ($lower !== null && $upper !== null) { + if ($lowerValue !== $upperValue) { + throw new RuntimeException( + "Service {$serviceId} has conflicting " + ."[{$normalizedKey}] property values." + ); } + + $mutations[(int) $upper->id] = [ + 'action' => 'delete', + 'id' => (int) $upper->id, + ]; + } elseif ($upper !== null) { + $mutations[(int) $upper->id] = [ + 'action' => 'rename', + 'id' => (int) $upper->id, + 'key' => $normalizedKey, + ]; } } - }); + } + + ksort($mutations); + + return array_values($mutations); + } + + private function strictPropertyValue( + ?object $property, + int $serviceId, + string $normalizedKey + ): ?int { + if ($property === null) { + return null; + } + + $value = StrictInteger::parseStoredDecimal($property->value); + if ($value === null) { + throw new RuntimeException( + "Service {$serviceId} has a non-integer " + ."[{$normalizedKey}] property value." + ); + } + + return $value; } public function down(): void { - // Key normalization is intentionally irreversible. Reintroducing uppercase - // keys would make Pterodactyl ignore the selected slider values again. + // Key normalization is intentionally irreversible. Reintroducing + // uppercase keys would make Pterodactyl ignore slider values again. } }; diff --git a/database/migrations/2026_07_26_000001_add_durable_fulfillment_to_ptero_reservations.php b/database/migrations/2026_07_26_000001_add_durable_fulfillment_to_ptero_reservations.php index 5f2a04f..9c4614f 100644 --- a/database/migrations/2026_07_26_000001_add_durable_fulfillment_to_ptero_reservations.php +++ b/database/migrations/2026_07_26_000001_add_durable_fulfillment_to_ptero_reservations.php @@ -20,9 +20,9 @@ public function up(): void if (in_array($driver, ['mysql', 'mariadb'], true)) { DB::statement( - "ALTER TABLE ptero_resource_reservations MODIFY status " - . "ENUM('pending','paid_committed','confirmed','expired','cancelled') " - . "NOT NULL DEFAULT 'pending'" + 'ALTER TABLE ptero_resource_reservations MODIFY status ' + ."ENUM('pending','paid_committed','confirmed','expired','cancelled') " + ."NOT NULL DEFAULT 'pending'" ); } elseif ($driver === 'sqlite') { // Laravel represents SQLite enums as CHECK-constrained text. @@ -173,9 +173,9 @@ public function down(): void $driver = DB::getDriverName(); if (in_array($driver, ['mysql', 'mariadb'], true)) { DB::statement( - "ALTER TABLE ptero_resource_reservations MODIFY status " - . "ENUM('pending','confirmed','expired','cancelled') " - . "NOT NULL DEFAULT 'pending'" + 'ALTER TABLE ptero_resource_reservations MODIFY status ' + ."ENUM('pending','confirmed','expired','cancelled') " + ."NOT NULL DEFAULT 'pending'" ); } elseif ($driver === 'sqlite') { Schema::table( diff --git a/database/migrations/2026_07_26_000003_add_cpu_alert_thresholds.php b/database/migrations/2026_07_26_000003_add_cpu_alert_thresholds.php index d3d0ddc..a18d19d 100644 --- a/database/migrations/2026_07_26_000003_add_cpu_alert_thresholds.php +++ b/database/migrations/2026_07_26_000003_add_cpu_alert_thresholds.php @@ -24,8 +24,8 @@ public function up(): void 'ptero_alert_configs', function (Blueprint $table) use ($addWarning, $addCritical): void { if ($addWarning) { - $table->unsignedTinyInteger('cpu_warning_threshold') - ->default(80); + $table->unsignedTinyInteger('cpu_warning_threshold') + ->default(80); } if ($addCritical) { $table->unsignedTinyInteger('cpu_critical_threshold') @@ -54,9 +54,9 @@ public function down(): void Schema::table( 'ptero_alert_configs', function (Blueprint $table) use ($columns): void { - if ($columns !== []) { - $table->dropColumn($columns); - } + if ($columns !== []) { + $table->dropColumn($columns); + } } ); } diff --git a/database/migrations/2026_07_26_000005_widen_reservation_price.php b/database/migrations/2026_07_26_000005_widen_reservation_price.php index 0985390..8f07f63 100644 --- a/database/migrations/2026_07_26_000005_widen_reservation_price.php +++ b/database/migrations/2026_07_26_000005_widen_reservation_price.php @@ -22,7 +22,7 @@ public function down(): void (float) DB::table('ptero_resource_reservations') ->max('calculated_price') > 99_999_999.99 ) { - throw new \RuntimeException( + throw new RuntimeException( 'Reservation prices no longer fit the legacy DECIMAL(10,2) column.' ); } diff --git a/database/migrations/2026_07_26_000030_enforce_one_checkout_commitment_per_service.php b/database/migrations/2026_07_26_000030_enforce_one_checkout_commitment_per_service.php index 96b8f24..627ebd4 100644 --- a/database/migrations/2026_07_26_000030_enforce_one_checkout_commitment_per_service.php +++ b/database/migrations/2026_07_26_000030_enforce_one_checkout_commitment_per_service.php @@ -65,8 +65,7 @@ public function down(): void ); Schema::table( 'ptero_resource_reservations', - fn (Blueprint $table) => - $table->dropColumn('service_guard_id') + fn (Blueprint $table) => $table->dropColumn('service_guard_id') ); } else { Schema::table('ptero_resource_reservations', function (Blueprint $table) { @@ -137,7 +136,7 @@ private function assertNoDuplicateCheckoutCommitments(): void }) ->implode('; '); - throw new \RuntimeException( + throw new RuntimeException( 'Dynamic Pterodactyl found duplicate active checkout ' .'commitments and refused to retire or release any obligation. ' .'Reconcile every invoice, signed configuration, allocation, and ' diff --git a/database/migrations/2026_07_26_000040_restrict_durable_reservation_parent_deletes.php b/database/migrations/2026_07_26_000040_restrict_durable_reservation_parent_deletes.php new file mode 100644 index 0000000..9a3a4ca --- /dev/null +++ b/database/migrations/2026_07_26_000040_restrict_durable_reservation_parent_deletes.php @@ -0,0 +1,87 @@ +dropForeign(['service_id']); + $table->dropForeign(['user_id']); + + $table->foreign('service_id') + ->references('id') + ->on('services') + ->restrictOnDelete(); + $table->foreign('user_id') + ->references('id') + ->on('users') + ->restrictOnDelete(); + } + ); + $this->restoreSqlitePartialIndexes(); + } + + public function down(): void + { + Schema::table( + 'ptero_resource_reservations', + function (Blueprint $table): void { + $table->dropForeign(['service_id']); + $table->dropForeign(['user_id']); + + $table->foreign('service_id') + ->references('id') + ->on('services') + ->nullOnDelete(); + $table->foreign('user_id') + ->references('id') + ->on('users') + ->nullOnDelete(); + } + ); + $this->restoreSqlitePartialIndexes(); + } + + /** + * Laravel rebuilds SQLite tables to alter foreign keys. Recreate the two + * conditional uniqueness guards because SQLite schema introspection does + * not retain partial-index predicates during that rebuild. + */ + private function restoreSqlitePartialIndexes(): void + { + if (DB::getDriverName() !== 'sqlite') { + return; + } + + DB::statement( + 'DROP INDEX IF EXISTS ' + .'ptero_reservations_active_upgrade_unique' + ); + DB::statement( + 'CREATE UNIQUE INDEX ptero_reservations_active_upgrade_unique ' + .'ON ptero_resource_reservations (upgrade_guard_id) ' + ."WHERE purpose = 'upgrade' " + ."AND status IN ('pending', 'paid_committed') " + .'AND upgrade_guard_id IS NOT NULL' + ); + DB::statement( + 'DROP INDEX IF EXISTS ' + .'ptero_reservations_active_checkout_service_unique' + ); + DB::statement( + 'CREATE UNIQUE INDEX ' + .'ptero_reservations_active_checkout_service_unique ' + .'ON ptero_resource_reservations (service_guard_id) ' + ."WHERE purpose = 'checkout' " + ."AND status IN ('pending', 'paid_committed', 'confirmed') " + .'AND service_guard_id IS NOT NULL' + ); + } +}; diff --git a/database/migrations/2026_07_26_000050_create_scheduler_heartbeats_table.php b/database/migrations/2026_07_26_000050_create_scheduler_heartbeats_table.php new file mode 100644 index 0000000..878ac59 --- /dev/null +++ b/database/migrations/2026_07_26_000050_create_scheduler_heartbeats_table.php @@ -0,0 +1,79 @@ +id(); + $table->string('task_name')->unique(); + $table->unsignedInteger('expected_interval_seconds'); + $table->unsignedInteger('lag_threshold_seconds'); + $table->timestamp('last_started_at')->nullable(); + $table->timestamp('last_completed_at')->nullable(); + $table->timestamp('last_succeeded_at')->nullable(); + $table->timestamp('last_failed_at')->nullable(); + $table->timestamp('last_lag_checked_at')->nullable(); + $table->timestamp('lag_detected_at')->nullable(); + $table->timestamp('last_alerted_at')->nullable(); + $table->unsignedInteger('last_processed_count')->default(0); + $table->unsignedInteger('last_failure_count')->default(0); + $table->unsignedInteger('consecutive_failures')->default(0); + $table->text('last_error')->nullable(); + $table->json('last_failure_context')->nullable(); + $table->timestamps(); + + $table->index('last_succeeded_at'); + $table->index('lag_detected_at'); + }); + + $now = now(); + DB::table('ptero_scheduler_heartbeats')->insert([ + [ + 'task_name' => 'expire_checkout_reservations', + 'expected_interval_seconds' => 60, + 'lag_threshold_seconds' => 300, + 'created_at' => $now, + 'updated_at' => $now, + ], + [ + 'task_name' => 'expire_unpaid_upgrades', + 'expected_interval_seconds' => 60, + 'lag_threshold_seconds' => 300, + 'created_at' => $now, + 'updated_at' => $now, + ], + [ + 'task_name' => 'reconcile_paid_checkout_commitments', + 'expected_interval_seconds' => 600, + 'lag_threshold_seconds' => 1800, + 'created_at' => $now, + 'updated_at' => $now, + ], + [ + 'task_name' => 'reconcile_stalled_upgrades', + 'expected_interval_seconds' => 600, + 'lag_threshold_seconds' => 1800, + 'created_at' => $now, + 'updated_at' => $now, + ], + [ + 'task_name' => 'check_capacity_alerts', + 'expected_interval_seconds' => 300, + 'lag_threshold_seconds' => 900, + 'created_at' => $now, + 'updated_at' => $now, + ], + ]); + } + + public function down(): void + { + Schema::dropIfExists('ptero_scheduler_heartbeats'); + } +}; diff --git a/database/migrations/2026_07_26_000060_allow_system_audit_entries.php b/database/migrations/2026_07_26_000060_allow_system_audit_entries.php new file mode 100644 index 0000000..2236244 --- /dev/null +++ b/database/migrations/2026_07_26_000060_allow_system_audit_entries.php @@ -0,0 +1,43 @@ +dropForeign(['user_id']); + $table->unsignedBigInteger('user_id')->nullable()->change(); + $table->foreign('user_id') + ->references('id') + ->on('users') + ->nullOnDelete(); + }); + } + + public function down(): void + { + if ( + DB::table('ptero_audit_logs') + ->whereNull('user_id') + ->exists() + ) { + throw new RuntimeException( + 'System audit entries must be retained before this migration can be rolled back.' + ); + } + + Schema::table('ptero_audit_logs', function (Blueprint $table): void { + $table->dropForeign(['user_id']); + $table->unsignedBigInteger('user_id')->nullable(false)->change(); + $table->foreign('user_id') + ->references('id') + ->on('users') + ->cascadeOnDelete(); + }); + } +}; diff --git a/database/migrations/2026_07_26_000070_add_scan_cursor_to_scheduler_heartbeats.php b/database/migrations/2026_07_26_000070_add_scan_cursor_to_scheduler_heartbeats.php new file mode 100644 index 0000000..4c05619 --- /dev/null +++ b/database/migrations/2026_07_26_000070_add_scan_cursor_to_scheduler_heartbeats.php @@ -0,0 +1,28 @@ +unsignedBigInteger('last_scanned_entity_id') + ->default(0) + ->after('last_alerted_at'); + } + ); + } + + public function down(): void + { + Schema::table( + 'ptero_scheduler_heartbeats', + fn (Blueprint $table) => $table->dropColumn('last_scanned_entity_id') + ); + } +}; diff --git a/migration-readiness.php b/migration-readiness.php index 7efd83b..05b5c5c 100644 --- a/migration-readiness.php +++ b/migration-readiness.php @@ -353,7 +353,7 @@ public function assertReady(): void ); } - throw new \RuntimeException( + throw new RuntimeException( 'Dynamic Pterodactyl cannot finish upgrading because its dynamic ' .'stock schema or fulfillment proofs are incomplete: ' .implode('; ', $details) @@ -588,8 +588,7 @@ private function requireSignedAllocationClaims( } usort( $expected, - fn (array $left, array $right): int => - $left['allocation_id'] <=> $right['allocation_id'] + fn (array $left, array $right): int => $left['allocation_id'] <=> $right['allocation_id'] ); $claims = DB::table('ptero_reservation_allocations') @@ -618,12 +617,10 @@ private function requireSignedAllocationClaims( || ( $reservation->status === 'confirmed' ? $claims->contains( - fn (object $allocation): bool => - $allocation->released_at === null + fn (object $allocation): bool => $allocation->released_at === null ) : $claims->contains( - fn (object $allocation): bool => - $allocation->released_at !== null + fn (object $allocation): bool => $allocation->released_at !== null ) ) ) { @@ -868,7 +865,7 @@ private function missingActiveUpgradeReservations(): array $currentProduct = $upgrade->service?->product; $targetProduct = $upgrade->product; if ($currentProduct === null || $targetProduct === null) { - throw new \RuntimeException( + throw new RuntimeException( 'The active upgrade product identity is missing.' ); } @@ -898,7 +895,7 @@ private function missingActiveUpgradeReservations(): array $upgrade ) ); - } catch (\Throwable) { + } catch (Throwable) { $dynamic = true; $classificationFailed = true; } @@ -1196,7 +1193,7 @@ private function productPanelMatchesCheckout( $panelIdentity = PanelEndpointIdentity::hash( trim((string) ($settings['host'] ?? '')) ); - } catch (\Throwable) { + } catch (Throwable) { return false; } @@ -1362,7 +1359,7 @@ private function checkoutPricingMatches( 'calculated_price' => $reservationAmount, 'config_options' => $configOptions, ]); - } catch (\Throwable) { + } catch (Throwable) { return false; } @@ -1429,11 +1426,11 @@ private function checkoutResourceOptionsMatch( $selected[$resource] = $value; $optionIds[$optionId] = $resource; } + return ! ( $selected === [] || collect($selected)->contains( - fn (int $value, string $resource): bool => - $value !== $payloadResources[$resource] + fn (int $value, string $resource): bool => $value !== $payloadResources[$resource] ) ); } @@ -1446,7 +1443,7 @@ private function checkoutInvoiceMatches( $amount = $this->normalizedMoney( $reservation->calculated_price ?? null ); - } catch (\Throwable) { + } catch (Throwable) { return false; } if ($amount[0] === '-') { @@ -1491,7 +1488,7 @@ private function checkoutInvoiceMatches( try { $lineAmount = $this->normalizedMoney($item->price); - } catch (\Throwable) { + } catch (Throwable) { return false; } @@ -1549,7 +1546,7 @@ private function currentServiceProperties(Service $service): ?array } $properties[$key] = $numericValue; } - } catch (\Throwable) { + } catch (Throwable) { return null; } @@ -1751,7 +1748,7 @@ private function upgradeFingerprintMatches( 'invoice', ]) ->find($upgradeId); - } catch (\Throwable) { + } catch (Throwable) { return false; } if ($upgrade === null || $upgrade->service === null) { @@ -1950,7 +1947,7 @@ private function upgradeFingerprintMatches( ['pending', 'paid_committed'], true ) || $upgrade->sourceStillMatches(); - } catch (\Throwable) { + } catch (Throwable) { return false; } @@ -2168,7 +2165,7 @@ private function decodedArray(mixed $value): ?array 512, JSON_THROW_ON_ERROR ); - } catch (\JsonException) { + } catch (JsonException) { return null; } @@ -2188,7 +2185,7 @@ private function snapshotFingerprint(?array $snapshot): ?string | JSON_PRESERVE_ZERO_FRACTION | JSON_UNESCAPED_SLASHES )); - } catch (\JsonException) { + } catch (JsonException) { return null; } } @@ -2426,21 +2423,15 @@ private function upgradeFingerprint( return hash('sha256', json_encode( $this->canonicalizeUpgradeSnapshot([ 'upgrade_id' => (int) $upgrade->id, - 'source_fingerprint' => - (string) $upgrade->source_fingerprint, - 'target_fingerprint' => - (string) $upgrade->target_fingerprint, + 'source_fingerprint' => (string) $upgrade->source_fingerprint, + 'target_fingerprint' => (string) $upgrade->target_fingerprint, 'panel_identity' => $payload['panel_identity'], 'node_id' => $payload['node_id'], 'location_id' => $payload['location_id'], - 'external_server_id' => - $payload['external_server_id'], - 'external_server_uuid' => - $payload['external_server_uuid'], - 'external_server_identifier' => - $payload['external_server_identifier'], - 'external_server_external_id' => - $payload['external_server_external_id'], + 'external_server_id' => $payload['external_server_id'], + 'external_server_uuid' => $payload['external_server_uuid'], + 'external_server_identifier' => $payload['external_server_identifier'], + 'external_server_external_id' => $payload['external_server_external_id'], 'external_user_id' => $payload['external_user_id'], 'user_external_id' => $payload['user_external_id'], 'user_email' => $payload['user_email'], @@ -2448,16 +2439,14 @@ private function upgradeFingerprint( 'egg_id' => $payload['egg_id'], 'preserved_build' => $payload['preserved_build'], 'allocation_id' => $payload['allocation_id'], - 'assigned_allocation_ids' => - $payload['assigned_allocation_ids'], + 'assigned_allocation_ids' => $payload['assigned_allocation_ids'], 'source' => $payload['source'], 'target' => $payload['target'], 'delta' => $payload['delta'], 'quoted_amount' => $this->normalizedMoney( $upgrade->quoted_amount ), - 'currency_code' => - strtoupper((string) $upgrade->currency_code), + 'currency_code' => strtoupper((string) $upgrade->currency_code), ]), JSON_THROW_ON_ERROR | JSON_PRESERVE_ZERO_FRACTION @@ -2472,8 +2461,7 @@ private function upgradePricingVersion( 'quoted_amount' => $this->normalizedMoney( $upgrade->quoted_amount ), - 'currency_code' => - strtoupper((string) $upgrade->currency_code), + 'currency_code' => strtoupper((string) $upgrade->currency_code), ], JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES)); } @@ -2514,7 +2502,7 @@ private function upgradeInvoiceMatches( try { $lineAmount = $this->normalizedMoney($item->price); - } catch (\Throwable) { + } catch (Throwable) { return false; } @@ -2553,7 +2541,7 @@ private function checkoutIdentityMatchesUpgrade( 512, JSON_THROW_ON_ERROR ); - } catch (\JsonException) { + } catch (JsonException) { return false; } if (! is_array($checkoutPayload)) { @@ -2656,7 +2644,7 @@ private function productPanelMatchesUpgrade( $panelIdentity = PanelEndpointIdentity::hash( trim((string) ($settings['host'] ?? '')) ); - } catch (\Throwable) { + } catch (Throwable) { return false; } @@ -2786,7 +2774,7 @@ private function decodedPayload( 512, JSON_THROW_ON_ERROR ); - } catch (\JsonException) { + } catch (JsonException) { $payload = null; } if (! is_array($payload)) { @@ -2865,7 +2853,7 @@ private function normalizedMoney(mixed $value): string } elseif (is_string($value)) { $text = $value; } else { - throw new \UnexpectedValueException( + throw new UnexpectedValueException( 'The upgrade quote amount is invalid.' ); } @@ -2877,7 +2865,7 @@ private function normalizedMoney(mixed $value): string $matches ) !== 1 ) { - throw new \UnexpectedValueException( + throw new UnexpectedValueException( 'The upgrade quote amount is invalid.' ); } @@ -2887,7 +2875,7 @@ private function normalizedMoney(mixed $value): string strlen($fraction) > 2 && trim(substr($fraction, 2), '0') !== '' ) { - throw new \UnexpectedValueException( + throw new UnexpectedValueException( 'The upgrade quote amount exceeds cent precision.' ); } diff --git a/resources/views/admin/dashboard.blade.php b/resources/views/admin/dashboard.blade.php index 292d2bb..28f8937 100644 --- a/resources/views/admin/dashboard.blade.php +++ b/resources/views/admin/dashboard.blade.php @@ -33,8 +33,14 @@ -
30-Day Revenue
-
${{ number_format($stats['confirmed_revenue'] ?? 0, 2) }}
+
30-Day Confirmed Revenue
+
+ @forelse(($stats['confirmed_revenue_by_currency'] ?? []) as $currency => $amount) +
{{ $currency }} {{ $amount }}
+ @empty +
+ @endforelse +
diff --git a/routes/api.php b/routes/api.php index a28299a..18391ba 100644 --- a/routes/api.php +++ b/routes/api.php @@ -7,11 +7,11 @@ */ use Illuminate\Support\Facades\Route; +use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\Admin\AdminCapacityController; +use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\Admin\AdminReservationController; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\AvailabilityController; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\ResourceQuoteController; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\UpgradeQuoteController; -use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\Admin\AdminCapacityController; -use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Controllers\Api\Admin\AdminReservationController; use Paymenter\Extensions\Others\DynamicPterodactyl\Http\Middleware\EnsureUserIsAdmin; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\QuoteRateLimiterService; diff --git a/tests/Feature/AlertConfigResourceTest.php b/tests/Feature/AlertConfigResourceTest.php new file mode 100644 index 0000000..80c6760 --- /dev/null +++ b/tests/Feature/AlertConfigResourceTest.php @@ -0,0 +1,42 @@ +shouldReceive('getLocations') + ->once() + ->andReturn([ + ['id' => 7, 'long' => 'Sydney'], + ['id' => 42, 'long' => 'Melbourne'], + ]); + $this->app->instance(ResourceCalculationService::class, $resources); + + $method = new \ReflectionMethod( + AlertConfigResource::class, + 'getScopedLocationOptions' + ); + $method->setAccessible(true); + $options = $method->invoke(null); + + $this->assertSame([ + '' => 'Global (All Locations)', + 7 => 'Sydney', + 42 => 'Melbourne', + ], $options); + } +} diff --git a/tests/Feature/AlertScheduleTest.php b/tests/Feature/AlertScheduleTest.php index c85d98a..7e4b232 100644 --- a/tests/Feature/AlertScheduleTest.php +++ b/tests/Feature/AlertScheduleTest.php @@ -3,23 +3,37 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Feature; use Illuminate\Console\Scheduling\Schedule; +use Illuminate\Support\Collection; +use Mockery; use Paymenter\Extensions\Others\DynamicPterodactyl\DynamicPterodactyl; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\SchedulerHealthService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; class AlertScheduleTest extends LaravelTestCase { private ?object $capacityAlertEvent = null; + /** @var Collection */ + private $events; + protected function setUp(): void { parent::setUp(); (new DynamicPterodactyl)->boot(); - $this->capacityAlertEvent = collect(app(Schedule::class)->events()) + $this->events = collect(app(Schedule::class)->events()); + $this->capacityAlertEvent = $this->events ->first(fn ($event) => $event->description === 'dynamic-pterodactyl:check-capacity-alerts'); } + protected function tearDown(): void + { + Mockery::close(); + + parent::tearDown(); + } + public function test_capacity_alert_schedule_is_registered(): void { $this->assertNotNull($this->capacityAlertEvent); @@ -31,4 +45,84 @@ public function test_capacity_alert_schedule_uses_without_overlapping(): void $this->assertNotNull($this->capacityAlertEvent); $this->assertTrue($this->capacityAlertEvent->withoutOverlapping); } + + public function test_lifecycle_task_types_have_independent_events(): void + { + $expected = [ + 'dynamic-pterodactyl:expire-checkout-reservations' => '* * * * *', + 'dynamic-pterodactyl:expire-upgrade-reservations' => '* * * * *', + 'dynamic-pterodactyl:reconcile-paid-checkout-commitments' => '*/10 * * * *', + 'dynamic-pterodactyl:reconcile-paid-upgrades' => '*/10 * * * *', + 'dynamic-pterodactyl:check-capacity-alerts' => '*/5 * * * *', + 'dynamic-pterodactyl:monitor-scheduler-health' => '*/5 * * * *', + ]; + + foreach ($expected as $description => $expression) { + $matching = $this->events->filter( + fn ($event) => $event->description === $description + ); + + $this->assertCount( + 1, + $matching, + "Expected one independent scheduler event [{$description}]." + ); + $event = $matching->first(); + $this->assertSame($expression, $event->expression); + $this->assertTrue($event->withoutOverlapping); + } + } + + public function test_failed_expiry_callback_does_not_share_upgrade_callback(): void + { + $health = Mockery::mock(SchedulerHealthService::class); + $health->shouldReceive('run') + ->once() + ->with( + SchedulerHealthService::TASK_EXPIRE_CHECKOUT, + Mockery::type(\Closure::class) + ) + ->andThrow(new \RuntimeException('checkout cleanup failed')); + $health->shouldReceive('run') + ->once() + ->with( + SchedulerHealthService::TASK_EXPIRE_UPGRADES, + Mockery::type(\Closure::class) + ) + ->andReturn(0); + $this->app->instance(SchedulerHealthService::class, $health); + + try { + ($this->callbackFor( + 'dynamic-pterodactyl:expire-checkout-reservations' + ))(); + $this->fail('Expected the checkout callback to fail.'); + } catch (\RuntimeException $exception) { + $this->assertSame( + 'checkout cleanup failed', + $exception->getMessage() + ); + } + + $this->assertSame( + 0, + ($this->callbackFor( + 'dynamic-pterodactyl:expire-upgrade-reservations' + ))() + ); + } + + private function callbackFor(string $description): \Closure + { + $event = $this->events->first( + fn ($candidate) => $candidate->description === $description + ); + $this->assertNotNull($event); + $property = new \ReflectionProperty($event, 'callback'); + $property->setAccessible(true); + $callback = $property->getValue($event); + $this->assertInstanceOf(\Closure::class, $callback); + + return $callback; + } } diff --git a/tests/Feature/AuditLogServiceTest.php b/tests/Feature/AuditLogServiceTest.php new file mode 100644 index 0000000..30509b5 --- /dev/null +++ b/tests/Feature/AuditLogServiceTest.php @@ -0,0 +1,100 @@ +log( + 'scheduler_reconciled', + 'scheduler', + 1 + ); + + $this->assertDatabaseHas('ptero_audit_logs', [ + 'id' => $auditId, + 'user_id' => null, + 'user_name' => 'System', + 'user_email' => 'system@localhost', + ]); + } + + public function test_deleting_an_operator_retains_and_anonymizes_audit_history(): void + { + $operator = User::factory()->create(); + Auth::login($operator); + $auditId = app(AuditLogService::class)->log( + 'configuration_updated', + 'product_config', + 42 + ); + Auth::logout(); + + $operator->delete(); + + $this->assertDatabaseMissing('users', ['id' => $operator->id]); + $this->assertDatabaseHas('ptero_audit_logs', [ + 'id' => $auditId, + 'user_id' => null, + 'user_name' => $operator->name, + 'user_email' => $operator->email, + ]); + } + + public function test_audit_user_foreign_key_sets_null_instead_of_cascading(): void + { + $rule = DB::getDriverName() === 'sqlite' + ? collect(DB::select( + "PRAGMA foreign_key_list('ptero_audit_logs')" + )) + ->first( + fn (object $foreignKey): bool => (string) $foreignKey->from === 'user_id' + ) + ?->on_delete + : DB::table( + 'information_schema.REFERENTIAL_CONSTRAINTS as constraints' + ) + ->join( + 'information_schema.KEY_COLUMN_USAGE as columns', + function ($join): void { + $join->on( + 'columns.CONSTRAINT_SCHEMA', + '=', + 'constraints.CONSTRAINT_SCHEMA' + )->on( + 'columns.CONSTRAINT_NAME', + '=', + 'constraints.CONSTRAINT_NAME' + )->on( + 'columns.TABLE_NAME', + '=', + 'constraints.TABLE_NAME' + ); + } + ) + ->where( + 'constraints.CONSTRAINT_SCHEMA', + DB::getDatabaseName() + ) + ->where( + 'constraints.TABLE_NAME', + 'ptero_audit_logs' + ) + ->where('columns.COLUMN_NAME', 'user_id') + ->value('constraints.DELETE_RULE'); + + $this->assertSame('SET NULL', strtoupper((string) $rule)); + } +} diff --git a/tests/Feature/AvailabilityApiTest.php b/tests/Feature/AvailabilityApiTest.php index eecc62f..e95609f 100644 --- a/tests/Feature/AvailabilityApiTest.php +++ b/tests/Feature/AvailabilityApiTest.php @@ -14,7 +14,7 @@ protected function setUp(): void { parent::setUp(); - require __DIR__ . '/../../routes/api.php'; + require __DIR__.'/../../routes/api.php'; } public function test_legacy_independent_maximum_availability_route_is_removed(): void diff --git a/tests/Feature/DurableReservationForeignKeyTest.php b/tests/Feature/DurableReservationForeignKeyTest.php new file mode 100644 index 0000000..eb9bbfb --- /dev/null +++ b/tests/Feature/DurableReservationForeignKeyTest.php @@ -0,0 +1,135 @@ +reservationDeleteRules(); + + $this->assertContains( + $deleteRules['service_id'] ?? null, + ['RESTRICT', 'NO ACTION'] + ); + $this->assertContains( + $deleteRules['user_id'] ?? null, + ['RESTRICT', 'NO ACTION'] + ); + $this->assertSame( + 'SET NULL', + $deleteRules['cart_item_id'] ?? null + ); + } + + public function test_sqlite_foreign_key_rebuild_preserves_partial_uniqueness_guards(): void + { + if (DB::getDriverName() !== 'sqlite') { + $this->markTestSkipped( + 'MariaDB uses generated-column uniqueness guards.' + ); + } + + $indexes = DB::table('sqlite_master') + ->where('type', 'index') + ->whereIn('name', [ + 'ptero_reservations_active_upgrade_unique', + 'ptero_reservations_active_checkout_service_unique', + ]) + ->pluck('sql', 'name') + ->map(fn (?string $sql): string => strtolower((string) $sql)); + + $this->assertStringContainsString( + "where purpose = 'upgrade'", + $indexes->get( + 'ptero_reservations_active_upgrade_unique', + '' + ) + ); + $this->assertStringContainsString( + "status in ('pending', 'paid_committed')", + $indexes->get( + 'ptero_reservations_active_upgrade_unique', + '' + ) + ); + $this->assertStringContainsString( + "where purpose = 'checkout'", + $indexes->get( + 'ptero_reservations_active_checkout_service_unique', + '' + ) + ); + $this->assertStringContainsString( + "status in ('pending', 'paid_committed', 'confirmed')", + $indexes->get( + 'ptero_reservations_active_checkout_service_unique', + '' + ) + ); + } + + /** + * @return array + */ + private function reservationDeleteRules(): array + { + if (DB::getDriverName() === 'sqlite') { + return collect(DB::select( + "PRAGMA foreign_key_list('ptero_resource_reservations')" + ))->mapWithKeys( + fn (object $foreignKey): array => [ + (string) $foreignKey->from => strtoupper((string) $foreignKey->on_delete), + ] + )->all(); + } + + return DB::table( + 'information_schema.REFERENTIAL_CONSTRAINTS as constraints' + ) + ->join( + 'information_schema.KEY_COLUMN_USAGE as columns', + function ($join): void { + $join->on( + 'columns.CONSTRAINT_SCHEMA', + '=', + 'constraints.CONSTRAINT_SCHEMA' + )->on( + 'columns.CONSTRAINT_NAME', + '=', + 'constraints.CONSTRAINT_NAME' + )->on( + 'columns.TABLE_NAME', + '=', + 'constraints.TABLE_NAME' + ); + } + ) + ->where( + 'constraints.CONSTRAINT_SCHEMA', + DB::getDatabaseName() + ) + ->where( + 'constraints.TABLE_NAME', + 'ptero_resource_reservations' + ) + ->whereIn('columns.COLUMN_NAME', [ + 'cart_item_id', + 'service_id', + 'user_id', + ]) + ->get([ + 'columns.COLUMN_NAME as column_name', + 'constraints.DELETE_RULE as delete_rule', + ]) + ->mapWithKeys( + fn (object $foreignKey): array => [ + (string) $foreignKey->column_name => strtoupper((string) $foreignKey->delete_rule), + ] + ) + ->all(); + } +} diff --git a/tests/Feature/LegacyReservationReadinessTest.php b/tests/Feature/LegacyReservationReadinessTest.php index 8694415..9da32c3 100644 --- a/tests/Feature/LegacyReservationReadinessTest.php +++ b/tests/Feature/LegacyReservationReadinessTest.php @@ -8,11 +8,12 @@ use App\Models\Plan; use App\Models\Price; use App\Models\Product; +use App\Models\Server; use App\Models\Service; use App\Models\ServiceUpgrade; -use App\Models\Server; use App\Models\User; use App\Services\Service\CapacityServiceCreationCoordinator; +use App\Services\ServiceUpgrade\ServiceUpgradeMutationCoordinator; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\DB; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\LegacyReservationReadinessService; @@ -118,9 +119,8 @@ public function test_upgrade_can_preserve_a_legitimate_new_node_and_allocation_i $payload, JSON_THROW_ON_ERROR ), - 'configuration_fingerprint' => - (new UpgradeReservationIntegrityService) - ->fingerprint($upgrade, $payload), + 'configuration_fingerprint' => (new UpgradeReservationIntegrityService) + ->fingerprint($upgrade, $payload), 'updated_at' => now(), ]); @@ -229,8 +229,7 @@ public function test_active_dynamic_upgrade_missing_reservation_blocks_migration $blocker = collect( (new LegacyReservationReadinessService)->blockers() )->first( - fn (array $row): bool => - $row['purpose'] === 'upgrade' + fn (array $row): bool => $row['purpose'] === 'upgrade' && in_array( "dynamic service upgrade #{$upgradeId} " .'requires exactly one coherent capacity reservation', @@ -259,8 +258,7 @@ public function test_upgrade_lifecycle_status_drift_blocks_migration(): void ); $this->assertTrue( $blockers->contains( - fn (array $row): bool => - $row['purpose'] === 'upgrade' + fn (array $row): bool => $row['purpose'] === 'upgrade' && in_array( "dynamic service upgrade #{$upgradeId} " .'requires exactly one coherent capacity reservation', @@ -327,8 +325,7 @@ public function test_service_bound_commitment_retired_by_legacy_migration_still_ 'status' => 'cancelled', 'configuration_fingerprint' => null, 'configuration_payload' => null, - 'admin_notes' => - 'Retired during migration to server-owned reservations.', + 'admin_notes' => 'Retired during migration to server-owned reservations.', ]); $blocker = collect( @@ -349,8 +346,7 @@ public function test_duplicate_commitment_retired_by_old_durable_migration_still $fixture['reservation_id'], [ 'status' => 'cancelled', - 'admin_notes' => - 'Retired duplicate service commitment during ' + 'admin_notes' => 'Retired duplicate service commitment during ' .'durable-fulfillment migration.', ] ); @@ -509,17 +505,15 @@ public function test_fractional_resource_identity_cannot_pass_readiness_by_integ 'status' => 'confirmed', 'server_extension_id' => 41, 'panel_identity' => $panel, - 'configuration_fingerprint' => - (new ReservationConfigurationService) - ->fingerprint($payload), + 'configuration_fingerprint' => (new ReservationConfigurationService) + ->fingerprint($payload), 'configuration_payload' => json_encode( $payload, JSON_THROW_ON_ERROR ), 'external_server_id' => 71, 'external_user_id' => 44, - 'external_server_uuid' => - '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', + 'external_server_uuid' => '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', 'external_server_identifier' => 'server-71', ]); $this->insertReleasedAllocation($reservationId, $panel); @@ -553,17 +547,15 @@ public function test_quantity_above_one_cannot_pass_legacy_readiness(): void 'quantity' => 2, 'server_extension_id' => 41, 'panel_identity' => $panel, - 'configuration_fingerprint' => - (new ReservationConfigurationService) - ->fingerprint($payload), + 'configuration_fingerprint' => (new ReservationConfigurationService) + ->fingerprint($payload), 'configuration_payload' => json_encode( $payload, JSON_THROW_ON_ERROR ), 'external_server_id' => 71, 'external_user_id' => 44, - 'external_server_uuid' => - '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', + 'external_server_uuid' => '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', 'external_server_identifier' => 'server-71', ]); $this->insertReleasedAllocation($reservationId, $panel); @@ -620,8 +612,7 @@ public function test_dynamic_service_missing_checkout_reservation_blocks_reverse collect( (new LegacyReservationReadinessService)->blockers() )->contains( - fn (array $row): bool => - $row['purpose'] === 'checkout' + fn (array $row): bool => $row['purpose'] === 'checkout' && $row['service_id'] === $fixture['service']->id && in_array( "dynamic service #{$fixture['service']->id} " @@ -652,8 +643,7 @@ public function test_duplicate_checkout_reservations_block_reverse_scan_even_wit $blocker = collect( (new LegacyReservationReadinessService)->blockers() )->first( - fn (array $row): bool => - $row['purpose'] === 'checkout' + fn (array $row): bool => $row['purpose'] === 'checkout' && $row['reservation_id'] === 0 && $row['service_id'] === $fixture['service']->id ); @@ -803,8 +793,7 @@ public function test_completed_upgrade_missing_reservation_blocks_reverse_scan() collect( (new LegacyReservationReadinessService)->blockers() )->contains( - fn (array $row): bool => - $row['purpose'] === 'upgrade' + fn (array $row): bool => $row['purpose'] === 'upgrade' && in_array( "dynamic service upgrade #{$upgradeId} " .'requires exactly one coherent capacity ' @@ -827,8 +816,7 @@ public function test_completed_upgrade_duplicate_reservations_block_reverse_scan collect( (new LegacyReservationReadinessService)->blockers() )->contains( - fn (array $row): bool => - $row['purpose'] === 'upgrade' + fn (array $row): bool => $row['purpose'] === 'upgrade' && $row['reservation_id'] === 0 && in_array( "dynamic service upgrade #{$upgradeId} " @@ -970,9 +958,8 @@ public function test_upgrade_source_and_target_billing_anchors_must_match(): voi $payload, JSON_THROW_ON_ERROR ), - 'configuration_fingerprint' => - (new UpgradeReservationIntegrityService) - ->fingerprint($upgrade, $payload), + 'configuration_fingerprint' => (new UpgradeReservationIntegrityService) + ->fingerprint($upgrade, $payload), 'updated_at' => now(), ]); @@ -1065,9 +1052,8 @@ private function insertCompleteCheckoutReservation( 'service_guard_id' => $service->id, 'server_extension_id' => $server->id, 'panel_identity' => $panel, - 'configuration_fingerprint' => - (new ReservationConfigurationService) - ->fingerprint($payload), + 'configuration_fingerprint' => (new ReservationConfigurationService) + ->fingerprint($payload), 'configuration_payload' => json_encode( $payload, JSON_THROW_ON_ERROR @@ -1248,8 +1234,7 @@ private function completeCheckoutPayload( $payload = [ 'customer_id' => $service->user_id, 'cart_id' => 99, - 'server_extension_id' => - (int) ($service->product?->server_id ?? 41), + 'server_extension_id' => (int) ($service->product?->server_id ?? 41), 'panel_identity' => $panel, 'product_id' => $service->product_id, 'plan_id' => $service->plan_id, @@ -1271,8 +1256,7 @@ private function completeCheckoutPayload( 'provisioning_identity' => [ 'nest_id' => 1, 'egg_id' => 2, - 'user_external_id' => - "paymenter-user-{$service->user_id}", + 'user_external_id' => "paymenter-user-{$service->user_id}", 'user_email' => (string) $service->user->email, ], 'allocations' => [[ @@ -1418,10 +1402,10 @@ private function insertCompleteUpgradeReservation(): int server: $server ); - $invoice = \App\Models\Invoice::factory()->create([ + $invoice = Invoice::factory()->create([ 'user_id' => $service->user_id, 'currency_code' => 'USD', - 'status' => \App\Models\Invoice::STATUS_PENDING, + 'status' => Invoice::STATUS_PENDING, ]); $upgrade = ServiceUpgrade::create([ 'service_id' => $service->id, @@ -1456,7 +1440,7 @@ private function insertCompleteUpgradeReservation(): int 'configs.configValue', ]); $upgrade->captureSnapshots(); - $upgrade->save(); + ServiceUpgradeMutationCoordinator::save($upgrade); $invoice->items()->create([ 'description' => 'Resource upgrade', 'price' => '100.00', @@ -1475,13 +1459,11 @@ private function insertCompleteUpgradeReservation(): int 'node_id' => 7, 'location_id' => 3, 'external_server_id' => 71, - 'external_server_uuid' => - '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', + 'external_server_uuid' => '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', 'external_server_identifier' => 'server-71', 'external_server_external_id' => (string) $service->id, 'external_user_id' => 44, - 'user_external_id' => - "paymenter-user-{$service->user_id}", + 'user_external_id' => "paymenter-user-{$service->user_id}", 'user_email' => (string) $service->user->email, 'nest_id' => 1, 'egg_id' => 2, @@ -1508,9 +1490,8 @@ private function insertCompleteUpgradeReservation(): int 'service_upgrade_id' => $upgradeId, 'upgrade_guard_id' => $upgradeId, 'panel_identity' => $panel, - 'configuration_fingerprint' => - (new UpgradeReservationIntegrityService) - ->fingerprint($upgrade, $payload), + 'configuration_fingerprint' => (new UpgradeReservationIntegrityService) + ->fingerprint($upgrade, $payload), 'configuration_payload' => json_encode( $payload, JSON_THROW_ON_ERROR @@ -1525,13 +1506,11 @@ private function insertCompleteUpgradeReservation(): int 'reserved_disk' => $delta['disk'], 'external_server_id' => 71, 'external_user_id' => 44, - 'external_server_uuid' => - '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', + 'external_server_uuid' => '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', 'external_server_identifier' => 'server-71', 'calculated_price' => '100.00', - 'pricing_version' => - (new UpgradeReservationIntegrityService) - ->pricingVersion($upgrade), + 'pricing_version' => (new UpgradeReservationIntegrityService) + ->pricingVersion($upgrade), 'formula_version' => 'dynamic-upgrade-v1', 'invoice_id' => $invoice->id, 'expires_at' => now()->addDay(), @@ -1735,8 +1714,7 @@ private function insertReservation( 'token' => bin2hex(random_bytes(32)), 'purpose' => 'checkout', 'server_extension_id' => 41, - 'panel_identity' => - hash('sha256', 'https://panel.example.com'), + 'panel_identity' => hash('sha256', 'https://panel.example.com'), 'service_id' => $service->id, 'service_guard_id' => $service->id, 'user_id' => $service->user_id, diff --git a/tests/Feature/NormalizeDynamicOptionKeysMigrationTest.php b/tests/Feature/NormalizeDynamicOptionKeysMigrationTest.php new file mode 100644 index 0000000..98247d1 --- /dev/null +++ b/tests/Feature/NormalizeDynamicOptionKeysMigrationTest.php @@ -0,0 +1,327 @@ +dynamicService(['memory']); + $propertyId = $this->insertProperty( + $service, + 'MEMORY', + '4096.0000' + ); + + $this->runMigration(); + + $this->assertSame( + 'memory', + DB::table('config_options') + ->where('id', $options['memory']->id) + ->value('env_variable') + ); + $this->assertDatabaseHas('properties', [ + 'id' => $propertyId, + 'model_type' => Service::class, + 'model_id' => $service->id, + 'key' => 'memory', + 'value' => '4096.0000', + ]); + $this->assertSame( + 1, + DB::table('properties') + ->where('model_type', Service::class) + ->where('model_id', $service->id) + ->count() + ); + } + + public function test_equal_uppercase_and_lowercase_properties_keep_the_canonical_row(): void + { + $this->requireCaseSensitivePropertyKeys(); + [$service] = $this->dynamicService(['memory']); + $upperId = $this->insertProperty( + $service, + 'MEMORY', + '4096.0000' + ); + $lowerId = $this->insertProperty( + $service, + 'memory', + '4096' + ); + + $this->runMigration(); + + $this->assertDatabaseMissing('properties', ['id' => $upperId]); + $this->assertDatabaseHas('properties', [ + 'id' => $lowerId, + 'key' => 'memory', + 'value' => '4096', + ]); + } + + public function test_conflicting_duplicate_values_abort_before_mutation(): void + { + $this->requireCaseSensitivePropertyKeys(); + [$service, $options] = $this->dynamicService(['memory']); + $this->insertProperty($service, 'MEMORY', '4096'); + $this->insertProperty($service, 'memory', '8192'); + + try { + $this->runMigration(); + $this->fail( + 'Conflicting legacy resource properties must block migration.' + ); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'conflicting [memory] property values', + $exception->getMessage() + ); + } + + $this->assertSame( + 'MEMORY', + DB::table('config_options') + ->where('id', $options['memory']->id) + ->value('env_variable') + ); + $this->assertSame( + 2, + DB::table('properties') + ->where('model_type', Service::class) + ->where('model_id', $service->id) + ->count() + ); + } + + public function test_non_integer_resource_value_aborts_before_mutation(): void + { + [$service, $options] = $this->dynamicService(['memory']); + $propertyId = $this->insertProperty( + $service, + 'MEMORY', + '4096.5' + ); + + try { + $this->runMigration(); + $this->fail( + 'Fractional resource properties must block migration.' + ); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'non-integer [memory] property value', + $exception->getMessage() + ); + } + + $this->assertSame( + 'MEMORY', + DB::table('config_options') + ->where('id', $options['memory']->id) + ->value('env_variable') + ); + $this->assertDatabaseHas('properties', [ + 'id' => $propertyId, + 'key' => 'MEMORY', + 'value' => '4096.5', + ]); + } + + public function test_later_invalid_key_casing_blocks_every_planned_change(): void + { + [$service, $options] = $this->dynamicService([ + 'memory', + 'cpu', + ]); + $memoryId = $this->insertProperty( + $service, + 'MEMORY', + '4096' + ); + $cpuId = $this->insertProperty($service, 'Cpu', '200'); + + try { + $this->runMigration(); + $this->fail( + 'Unexpected resource-key casing must block migration.' + ); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'unsupported resource key casing [Cpu]', + $exception->getMessage() + ); + } + + foreach ($options as $resource => $option) { + $this->assertSame( + strtoupper($resource), + DB::table('config_options') + ->where('id', $option->id) + ->value('env_variable') + ); + } + $this->assertDatabaseHas('properties', [ + 'id' => $memoryId, + 'key' => 'MEMORY', + ]); + $this->assertDatabaseHas('properties', [ + 'id' => $cpuId, + 'key' => 'Cpu', + ]); + } + + public function test_later_malformed_metadata_blocks_every_planned_change(): void + { + [$service, $options] = $this->dynamicService([ + 'memory', + 'cpu', + ]); + $memoryId = $this->insertProperty( + $service, + 'MEMORY', + '4096' + ); + DB::table('config_options') + ->where('id', $options['cpu']->id) + ->update(['metadata' => '{"resource_type":']); + + try { + $this->runMigration(); + $this->fail( + 'Malformed slider metadata must block migration.' + ); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + "Dynamic option {$options['cpu']->id} has invalid metadata", + $exception->getMessage() + ); + } + + foreach ($options as $resource => $option) { + $this->assertSame( + strtoupper($resource), + DB::table('config_options') + ->where('id', $option->id) + ->value('env_variable') + ); + } + $this->assertDatabaseHas('properties', [ + 'id' => $memoryId, + 'key' => 'MEMORY', + 'value' => '4096', + ]); + } + + /** + * @param array $resources + * @return array{ + * Service, + * array + * } + */ + private function dynamicService(array $resources): array + { + $server = Server::query()->create([ + 'name' => 'Pterodactyl', + 'extension' => 'Pterodactyl', + 'type' => 'server', + 'enabled' => true, + ]); + $product = Product::factory()->create([ + 'server_id' => $server->id, + ]); + $user = User::factory()->create(); + $serviceId = DB::table('services')->insertGetId([ + 'user_id' => $user->id, + 'product_id' => $product->id, + 'status' => Service::STATUS_CANCELLED, + 'currency_code' => 'USD', + 'quantity' => 1, + 'price' => '0.00', + 'created_at' => now(), + 'updated_at' => now(), + ]); + $service = Service::query()->findOrFail($serviceId); + $options = []; + + foreach ($resources as $resource) { + $option = ConfigOption::query()->create([ + 'name' => ucfirst($resource), + 'env_variable' => strtoupper($resource), + 'type' => 'dynamic_slider', + 'sort' => 0, + 'hidden' => false, + 'upgradable' => true, + 'metadata' => [ + 'resource_type' => $resource, + 'min' => 1, + 'max' => 100000, + 'step' => 1, + 'default' => 1, + 'display_divisor' => 1, + 'pricing' => [ + 'model' => 'linear', + 'rate_per_unit' => 0, + ], + ], + ]); + DB::table('config_option_products')->insert([ + 'config_option_id' => $option->id, + 'product_id' => $product->id, + ]); + $options[$resource] = $option; + } + + return [$service, $options]; + } + + private function insertProperty( + Service $service, + string $key, + string $value + ): int { + return DB::table('properties')->insertGetId([ + 'custom_property_id' => null, + 'name' => ucfirst(strtolower($key)), + 'key' => $key, + 'value' => $value, + 'model_type' => Service::class, + 'model_id' => $service->id, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + + private function runMigration(): void + { + $migration = require __DIR__ + .'/../../database/migrations/' + .'2026_07_25_000002_normalize_dynamic_option_keys.php'; + + $migration->up(); + } + + private function requireCaseSensitivePropertyKeys(): void + { + if (DB::getDriverName() !== 'sqlite') { + $this->markTestSkipped( + 'The production MariaDB unique key intentionally rejects ' + .'case-only duplicate properties.' + ); + } + } +} diff --git a/tests/Feature/ReservationStatisticsTest.php b/tests/Feature/ReservationStatisticsTest.php new file mode 100644 index 0000000..a31e946 --- /dev/null +++ b/tests/Feature/ReservationStatisticsTest.php @@ -0,0 +1,76 @@ +reservation('USD', '10.10', 'confirmed'); + $this->reservation('USD', '2.20', 'confirmed'); + $this->reservation('AUD', '7.00', 'confirmed'); + $this->reservation(null, '1.00', 'confirmed'); + $this->reservation('USD', '100.00', 'pending'); + $old = $this->reservation('USD', '50.00', 'confirmed'); + $old->forceFill([ + 'created_at' => now()->subDays(31), + 'updated_at' => now()->subDays(31), + ])->save(); + + $stats = app(ReservationService::class)->getStatistics('30d'); + + $this->assertSame([ + 'AUD' => '7.00', + 'UNSPECIFIED' => '1.00', + 'USD' => '12.30', + ], $stats['confirmed_revenue_by_currency']); + $this->assertArrayNotHasKey('confirmed_revenue', $stats); + } + + public function test_reservation_table_formats_each_rows_own_currency(): void + { + $formatter = new \ReflectionMethod( + ReservationResource::class, + 'formatPrice' + ); + $formatter->setAccessible(true); + + $this->assertSame( + 'AUD 12.30', + $formatter->invoke(null, '12.30', 'aud') + ); + $this->assertSame( + '12.30 (currency unavailable)', + $formatter->invoke(null, '12.30', null) + ); + } + + private function reservation( + ?string $currency, + string $price, + string $status + ): ResourceReservation { + return ResourceReservation::query()->create([ + 'token' => Str::random(64), + 'node_id' => 1, + 'location_id' => 1, + 'memory' => 4096, + 'cpu' => 200, + 'disk' => 20480, + 'currency_code' => $currency, + 'calculated_price' => $price, + 'pricing_breakdown' => [], + 'status' => $status, + 'expires_at' => now()->addDay(), + ]); + } +} diff --git a/tests/Feature/SetupWizardValidationTest.php b/tests/Feature/SetupWizardValidationTest.php index ba9bec3..f736c3d 100644 --- a/tests/Feature/SetupWizardValidationTest.php +++ b/tests/Feature/SetupWizardValidationTest.php @@ -39,7 +39,7 @@ protected function setUp(): void ->zeroOrMoreTimes() ->andReturn(hash('sha256', 'https://panel.example')); $this->app->instance(PterodactylInventoryService::class, $inventory); - $this->app['view']->addNamespace('dynamic-pterodactyl', __DIR__ . '/../../resources/views'); + $this->app['view']->addNamespace('dynamic-pterodactyl', __DIR__.'/../../resources/views'); } protected function tearDown(): void diff --git a/tests/Unit/AlertServiceTest.php b/tests/Unit/AlertServiceTest.php index 11a79c5..b5cb250 100644 --- a/tests/Unit/AlertServiceTest.php +++ b/tests/Unit/AlertServiceTest.php @@ -3,21 +3,26 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; use App\Models\User; +use Illuminate\Container\Container; +use Illuminate\Events\Dispatcher; use Illuminate\Foundation\Testing\DatabaseTransactions; +use Illuminate\Http\Client\Factory; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Event; +use Illuminate\Support\Facades\Facade; use Illuminate\Support\Facades\Http; -use Illuminate\Support\Facades\Notification; -use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Notification; use Mockery; +use Mockery\MockInterface; use Paymenter\Extensions\Others\DynamicPterodactyl\Events\AlertDeliveryFailed; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\AlertConfig; use Paymenter\Extensions\Others\DynamicPterodactyl\Notifications\CapacityAlertNotification; use Paymenter\Extensions\Others\DynamicPterodactyl\Notifications\ProvisioningFailedNotification; use Paymenter\Extensions\Others\DynamicPterodactyl\Notifications\ReservationShortfallNotification; -use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AuditLogService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AlertService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AuditLogService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceCalculationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\TestCase; @@ -36,8 +41,8 @@ protected function setUp(): void private function setFacadeApplication(?object $dispatcher = null): void { - $app = new \Illuminate\Container\Container; - $app->instance('events', $dispatcher ?? new \Illuminate\Events\Dispatcher($app)); + $app = new Container; + $app->instance('events', $dispatcher ?? new Dispatcher($app)); $app->instance('log', new class { public function emergency(...$arguments): void {} @@ -58,11 +63,11 @@ public function debug(...$arguments): void {} public function log(...$arguments): void {} }); - $app->instance('http', new \Illuminate\Http\Client\Factory); - \Illuminate\Support\Facades\Facade::setFacadeApplication($app); + $app->instance('http', new Factory); + Facade::setFacadeApplication($app); } - private function bindEventDispatcherMock(): \Mockery\MockInterface + private function bindEventDispatcherMock(): MockInterface { $dispatcher = Mockery::spy(\Illuminate\Contracts\Events\Dispatcher::class); $this->setFacadeApplication($dispatcher); @@ -217,7 +222,7 @@ public function test_notify_shortfall_no_admins_logs_warning(): void Log::spy(); $query = Mockery::mock(); - $query->shouldReceive('get')->once()->andReturn(new Collection()); + $query->shouldReceive('get')->once()->andReturn(new Collection); $user = Mockery::mock('alias:App\\Models\\User'); $user->shouldReceive('whereNotNull')->once()->with('role_id')->andReturn($query); @@ -271,7 +276,7 @@ public function notify($notification): void 'location_id' => 9, 'location_name' => 'AMS-1', 'email_notifications' => true, - 'notification_emails' => json_encode(['ops@example.com']), + 'notification_emails' => json_encode([]), 'webhook_notifications' => false, 'webhook_url' => null, ], @@ -290,12 +295,12 @@ public function notify($notification): void $this->assertSame('AMS-1', $recipientA->notifications[0]->alertConfig->location_name); } - public function test_capacity_alert_email_logs_warning_when_no_admins(): void + public function test_capacity_alert_email_logs_warning_when_no_recipients(): void { Log::spy(); $query = Mockery::mock(); - $query->shouldReceive('get')->once()->andReturn(new Collection()); + $query->shouldReceive('get')->once()->andReturn(new Collection); $user = Mockery::mock('alias:App\\Models\\User'); $user->shouldReceive('whereNotNull')->once()->with('role_id')->andReturn($query); @@ -308,7 +313,7 @@ public function test_capacity_alert_email_logs_warning_when_no_admins(): void 'location_id' => null, 'location_name' => null, 'email_notifications' => true, - 'notification_emails' => json_encode(['ops@example.com']), + 'notification_emails' => json_encode([]), 'webhook_notifications' => false, 'webhook_url' => null, ], @@ -322,7 +327,7 @@ public function test_capacity_alert_email_logs_warning_when_no_admins(): void ); Log::shouldHaveReceived('warning')->with( - 'No admin recipients configured for capacity alert', + 'No email recipients configured for capacity alert', Mockery::on(fn (array $context) => $context['alert_config_id'] === 99) ); } @@ -355,7 +360,7 @@ public function notify($notification): void 'location_id' => null, 'location_name' => null, 'email_notifications' => true, - 'notification_emails' => json_encode(['ops@example.com']), + 'notification_emails' => json_encode([]), 'webhook_notifications' => false, 'webhook_url' => null, ], @@ -415,7 +420,7 @@ public function notify($notification): void 'location_id' => 1, 'location_name' => 'DFW-1', 'email_notifications' => true, - 'notification_emails' => json_encode(['ops@example.com']), + 'notification_emails' => json_encode([]), 'webhook_notifications' => false, 'webhook_url' => null, ], @@ -439,7 +444,7 @@ public function test_alert_with_both_channels_failed_dispatches_alert_delivery_f Http::fake(['*' => Http::response('Server Error', 500)]); $query = Mockery::mock(); - $query->shouldReceive('get')->once()->andReturn(new Collection()); + $query->shouldReceive('get')->once()->andReturn(new Collection); $user = Mockery::mock('alias:App\Models\User'); $user->shouldReceive('whereNotNull')->once()->with('role_id')->andReturn($query); @@ -451,7 +456,7 @@ public function test_alert_with_both_channels_failed_dispatches_alert_delivery_f 'location_id' => 1, 'location_name' => 'Test', 'email_notifications' => true, - 'notification_emails' => json_encode(['ops@example.com']), + 'notification_emails' => json_encode([]), 'webhook_notifications' => true, 'webhook_url' => 'https://hooks.example.com/test', ], @@ -494,7 +499,7 @@ public function test_alert_with_no_recipients_does_not_deliver_email(): void Log::spy(); $query = Mockery::mock(); - $query->shouldReceive('get')->once()->andReturn(new Collection()); + $query->shouldReceive('get')->once()->andReturn(new Collection); $user = Mockery::mock('alias:App\Models\User'); $user->shouldReceive('whereNotNull')->once()->with('role_id')->andReturn($query); @@ -506,7 +511,7 @@ public function test_alert_with_no_recipients_does_not_deliver_email(): void 'location_id' => null, 'location_name' => null, 'email_notifications' => true, - 'notification_emails' => json_encode(['ops@example.com']), + 'notification_emails' => json_encode([]), 'webhook_notifications' => false, 'webhook_url' => null, ], @@ -516,9 +521,8 @@ public function test_alert_with_no_recipients_does_not_deliver_email(): void $this->assertFalse($result); $dispatcher->shouldHaveReceived('dispatch')->with(Mockery::type(AlertDeliveryFailed::class)); - Log::shouldHaveReceived('warning')->with('No admin recipients configured for capacity alert', Mockery::any()); + Log::shouldHaveReceived('warning')->with('No email recipients configured for capacity alert', Mockery::any()); } - } class AlertServiceAuditTest extends LaravelTestCase @@ -560,8 +564,7 @@ public function test_terminal_upgrade_failure_notifies_and_audits_full_identity( Notification::assertSentTo( $admin, ProvisioningFailedNotification::class, - fn (ProvisioningFailedNotification $notification): bool => - $notification->snapshot === $snapshot + fn (ProvisioningFailedNotification $notification): bool => $notification->snapshot === $snapshot ); $this->assertDatabaseHas('ptero_audit_logs', [ 'action' => 'upgrade_failure_alerted', @@ -765,7 +768,7 @@ public function test_capacity_alert_does_not_audit_failed_webhook_delivery(): vo Event::assertDispatched(AlertDeliveryFailed::class); } - public function test_capacity_alert_no_admins_dispatches_delivery_failed_event(): void + public function test_configured_email_delivers_without_an_admin_account(): void { Event::fake(); Notification::fake(); @@ -795,7 +798,16 @@ public function test_capacity_alert_no_admins_dispatches_delivery_failed_event() $service = $this->makeService($resourceService); $this->runCheck($service, $alertConfig); - Event::assertDispatched(AlertDeliveryFailed::class); + Notification::assertSentOnDemand( + CapacityAlertNotification::class, + fn ( + CapacityAlertNotification $notification, + array $channels, + object $notifiable + ): bool => $notifiable->routes['mail'] === 'ops@example.com' + && $channels === ['mail'] + ); + Event::assertNotDispatched(AlertDeliveryFailed::class); } public function test_capacity_alert_success_does_not_dispatch_delivery_failed_event(): void diff --git a/tests/Unit/AllocationSelectionServiceTest.php b/tests/Unit/AllocationSelectionServiceTest.php index aa8fd03..44e7d3b 100644 --- a/tests/Unit/AllocationSelectionServiceTest.php +++ b/tests/Unit/AllocationSelectionServiceTest.php @@ -9,7 +9,7 @@ class AllocationSelectionServiceTest extends TestCase { public function test_dedicated_claim_uses_one_otherwise_unused_ip(): void { - $selected = (new AllocationSelectionService())->select([ + $selected = (new AllocationSelectionService)->select([ [ 'id' => 1, 'ip' => '192.0.2.10', @@ -41,7 +41,7 @@ public function test_dedicated_claim_uses_one_otherwise_unused_ip(): void public function test_equivalent_ipv6_spellings_share_one_dedicated_ip_group(): void { - $selected = (new AllocationSelectionService())->select([ + $selected = (new AllocationSelectionService)->select([ [ 'id' => 10, 'ip' => '2001:db8::1', @@ -61,7 +61,7 @@ public function test_equivalent_ipv6_spellings_share_one_dedicated_ip_group(): v public function test_port_range_constrains_primary_but_not_preclaimed_extras(): void { - $selected = (new AllocationSelectionService())->select([ + $selected = (new AllocationSelectionService)->select([ [ 'id' => 20, 'ip' => '192.0.2.20', @@ -83,7 +83,7 @@ public function test_port_range_constrains_primary_but_not_preclaimed_extras(): public function test_dedicated_fixed_ports_must_exist_on_the_same_ip(): void { - $selected = (new AllocationSelectionService())->select([ + $selected = (new AllocationSelectionService)->select([ [ 'id' => 30, 'ip' => '192.0.2.30', @@ -103,7 +103,7 @@ public function test_dedicated_fixed_ports_must_exist_on_the_same_ip(): void public function test_repeated_port_across_ips_uses_lowest_allocation_id(): void { - $selected = (new AllocationSelectionService())->select([ + $selected = (new AllocationSelectionService)->select([ [ 'id' => 101, 'ip' => '192.0.2.11', @@ -121,7 +121,7 @@ public function test_repeated_port_across_ips_uses_lowest_allocation_id(): void public function test_dedicated_repeated_port_uses_lowest_eligible_ip_group(): void { - $selected = (new AllocationSelectionService())->select([ + $selected = (new AllocationSelectionService)->select([ [ 'id' => 202, 'ip' => '192.0.2.22', diff --git a/tests/Unit/CartItemCreatedListenerTest.php b/tests/Unit/CartItemCreatedListenerTest.php new file mode 100644 index 0000000..2d83b49 --- /dev/null +++ b/tests/Unit/CartItemCreatedListenerTest.php @@ -0,0 +1,106 @@ +cartItem(); + $listener = $this->listenerExpectingReservation($cartItem); + + $listener->handle(new Created($cartItem)); + + $this->addToAssertionCount(1); + } + + public function test_updated_dynamic_cart_item_replaces_or_refreshes_its_hold(): void + { + $cartItem = $this->cartItem(); + $listener = $this->listenerExpectingReservation($cartItem); + + $listener->handle(new Updated($cartItem)); + + $this->addToAssertionCount(1); + } + + public function test_product_without_dynamic_resources_does_not_reserve_or_log(): void + { + $cartItem = $this->cartItem(); + $reservations = Mockery::mock(ReservationService::class); + $reservations->shouldReceive('reserveForCartItem')->never(); + $configuration = Mockery::mock( + ReservationConfigurationService::class + ); + $configuration->shouldReceive('requiresReservation') + ->once() + ->with(91) + ->andReturn(false); + Log::shouldReceive('info')->never(); + + (new CartItemCreatedListener($reservations, $configuration)) + ->handle(new Created($cartItem)); + + $this->addToAssertionCount(1); + } + + private function listenerExpectingReservation( + CartItem $cartItem + ): CartItemCreatedListener { + $configuration = Mockery::mock( + ReservationConfigurationService::class + ); + $configuration->shouldReceive('requiresReservation') + ->once() + ->with(91) + ->andReturn(true); + $reservations = Mockery::mock(ReservationService::class); + $reservations->shouldReceive('reserveForCartItem') + ->once() + ->with($cartItem) + ->andReturn([ + 'id' => 73, + 'node_id' => 7, + 'expires_at' => '2026-07-27T04:30:00+00:00', + 'status' => 'pending', + ]); + Log::shouldReceive('info') + ->once() + ->with('Capacity reserved for cart item', [ + 'cart_item_id' => 42, + 'reservation_id' => 73, + 'node_id' => 7, + 'expires_at' => '2026-07-27T04:30:00+00:00', + ]); + + return new CartItemCreatedListener( + $reservations, + $configuration + ); + } + + private function cartItem(): CartItem + { + $cartItem = new CartItem; + $cartItem->id = 42; + $cartItem->product_id = 91; + + return $cartItem; + } +} diff --git a/tests/Unit/ConfigOptionSetupServiceTest.php b/tests/Unit/ConfigOptionSetupServiceTest.php index d1d79d9..5038cf1 100644 --- a/tests/Unit/ConfigOptionSetupServiceTest.php +++ b/tests/Unit/ConfigOptionSetupServiceTest.php @@ -44,7 +44,7 @@ protected function tearDown(): void parent::tearDown(); } - public function test_createDynamicSliderOptions_rolls_back_on_mid_batch_failure(): void + public function test_create_dynamic_slider_options_rolls_back_on_mid_batch_failure(): void { $product = $this->eligibleProduct(); @@ -73,7 +73,7 @@ public function test_createDynamicSliderOptions_rolls_back_on_mid_batch_failure( $this->assertSame(0, $this->countOptionsForProduct($product->id)); } - public function test_createDynamicSliderOptions_happy_path_creates_all_four(): void + public function test_create_dynamic_slider_options_happy_path_creates_all_four(): void { $product = $this->eligibleProduct(); diff --git a/tests/Unit/NodeSelectionServiceTest.php b/tests/Unit/NodeSelectionServiceTest.php index b336954..91da7d1 100644 --- a/tests/Unit/NodeSelectionServiceTest.php +++ b/tests/Unit/NodeSelectionServiceTest.php @@ -11,6 +11,7 @@ class NodeSelectionServiceTest extends LaravelTestCase { private NodeSelectionService $service; + private $mockResourceService; protected function setUp(): void @@ -20,7 +21,7 @@ protected function setUp(): void $this->mockResourceService = Mockery::mock(ResourceCalculationService::class); $this->service = new NodeSelectionService( $this->mockResourceService, - new AllocationSelectionService() + new AllocationSelectionService ); } diff --git a/tests/Unit/ProductResourceConfigurationServiceTest.php b/tests/Unit/ProductResourceConfigurationServiceTest.php index 6bb4316..76d0635 100644 --- a/tests/Unit/ProductResourceConfigurationServiceTest.php +++ b/tests/Unit/ProductResourceConfigurationServiceTest.php @@ -9,6 +9,7 @@ use Illuminate\Support\Facades\DB; use Mockery; use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidResourceSelectionException; +use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ProductResourceConfigurationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\PterodactylInventoryService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; @@ -212,7 +213,7 @@ public function test_non_empty_port_mapping_requires_server_port(): void ]); $this->expectException( - \Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException::class + InvalidStockConfigurationException::class ); $this->expectExceptionMessage('SERVER_PORT'); @@ -284,7 +285,7 @@ public function test_port_mapping_rejects_multiple_ports_for_one_egg_environment ]); $this->expectException( - \Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException::class + InvalidStockConfigurationException::class ); $this->expectExceptionMessage( 'may assign exactly one port to QUERY_PORT' @@ -374,7 +375,7 @@ public function test_port_array_cannot_silently_bypass_deployment_constraints(): ]); $this->expectException( - \Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException::class + InvalidStockConfigurationException::class ); $this->expectExceptionMessage('cannot combine'); @@ -413,7 +414,7 @@ public function test_static_node_and_cpu_pinning_cannot_bypass_dynamic_placement "Expected {$case['key']} to fail dynamic stock closed." ); } catch ( - \Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException + InvalidStockConfigurationException $exception ) { $this->assertStringContainsString( diff --git a/tests/Unit/PterodactylInventoryServiceTest.php b/tests/Unit/PterodactylInventoryServiceTest.php index 83ea470..cfabb55 100644 --- a/tests/Unit/PterodactylInventoryServiceTest.php +++ b/tests/Unit/PterodactylInventoryServiceTest.php @@ -26,8 +26,7 @@ protected function setUp(): void public function test_panel_identity_preserves_case_sensitive_path(): void { $inventory = new PterodactylInventoryService([ - 'pterodactyl_url' => - 'HTTPS://Panel.Example.com:443/PanelA/', + 'pterodactyl_url' => 'HTTPS://Panel.Example.com:443/PanelA/', 'pterodactyl_api_key' => 'application-key', 'exclusive_provisioning_control' => true, ]); diff --git a/tests/Unit/QuoteRateLimiterServiceTest.php b/tests/Unit/QuoteRateLimiterServiceTest.php index ac42d8d..50798db 100644 --- a/tests/Unit/QuoteRateLimiterServiceTest.php +++ b/tests/Unit/QuoteRateLimiterServiceTest.php @@ -6,11 +6,11 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\Facades\Route; -use PHPUnit\Framework\Attributes\DataProvider; use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\QuoteRateLimitConfigurationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\QuoteRateLimiterService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; +use PHPUnit\Framework\Attributes\DataProvider; class QuoteRateLimiterServiceTest extends LaravelTestCase { diff --git a/tests/Unit/ReservationConfigurationServiceTest.php b/tests/Unit/ReservationConfigurationServiceTest.php index d86a88f..3cb9b1d 100644 --- a/tests/Unit/ReservationConfigurationServiceTest.php +++ b/tests/Unit/ReservationConfigurationServiceTest.php @@ -4,6 +4,7 @@ use App\Models\Product; use App\Models\Service; +use App\Models\User; use App\Support\PanelEndpointIdentity; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationConfigurationService; use PHPUnit\Framework\TestCase; @@ -194,7 +195,7 @@ public function test_bound_service_uses_snapshot_when_product_defaults_change(): 'currency_code' => 'AUD', ], true); $service->exists = true; - $service->setRelation('user', new \App\Models\User([ + $service->setRelation('user', new User([ 'id' => 30, 'email' => 'renamed@example.com', ])); diff --git a/tests/Unit/ReservationServiceTest.php b/tests/Unit/ReservationServiceTest.php index 3d6dfe3..8e8a03b 100644 --- a/tests/Unit/ReservationServiceTest.php +++ b/tests/Unit/ReservationServiceTest.php @@ -3,10 +3,11 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; use App\Enums\InvoiceTransactionStatus; +use App\Exceptions\DisplayException; use App\Exceptions\PermanentProvisioningException; +use App\Helpers\ExtensionHelper; use App\Jobs\Server\CreateJob; use App\Jobs\Server\SuspendJob; -use App\Helpers\ExtensionHelper; use App\Models\Cart; use App\Models\CartItem; use App\Models\ConfigOption; @@ -38,6 +39,8 @@ use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ProductResourceConfigurationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationConfigurationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ReservationService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\SchedulerHealthService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\SchedulerOperatorAlertService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; class ReservationServiceTest extends LaravelTestCase @@ -89,8 +92,7 @@ public function test_guest_holds_transfer_with_cart_ownership(): void DB::table('ptero_resource_reservations') ->where('id', $reservationId) ->update([ - 'configuration_fingerprint' => - $this->configurationService->fingerprint($payload), + 'configuration_fingerprint' => $this->configurationService->fingerprint($payload), 'configuration_payload' => json_encode( $payload, JSON_THROW_ON_ERROR @@ -186,7 +188,7 @@ public function test_cart_reservation_rejects_resource_slider_added_after_checko $stockConfiguration ); - $this->expectException(\App\Exceptions\DisplayException::class); + $this->expectException(DisplayException::class); $this->expectExceptionMessage( 'Reload checkout and explicitly select every resource again.' ); @@ -253,10 +255,7 @@ public function test_admin_cancellation_rolls_back_status_when_allocation_releas $token = (string) DB::table('ptero_resource_reservations') ->where('id', $reservationId) ->value('token'); - $service = new class( - $this->nodeService, - $this->configurationService - ) extends ReservationService + $service = new class($this->nodeService, $this->configurationService) extends ReservationService { protected function releaseAllocationClaims( int $reservationId @@ -288,10 +287,145 @@ protected function releaseAllocationClaims( ); } + public function test_admin_extension_rejects_minutes_outside_the_short_hold_limit(): void + { + $reservationId = $this->insertReservation(); + $token = (string) DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('token'); + $originalExpiry = now()->addMinutes(15); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'expires_at' => $originalExpiry, + 'guaranteed_until' => $originalExpiry, + ]); + + foreach ([-1, 0, 61] as $minutes) { + try { + $this->service()->extend($token, $minutes); + $this->fail( + "Expected {$minutes} extension minutes to be rejected." + ); + } catch (\InvalidArgumentException $exception) { + $this->assertSame( + 'A reservation extension must be between 1 and 60 minutes.', + $exception->getMessage() + ); + } + } + + $reservation = ResourceReservation::query()->findOrFail( + $reservationId + ); + $this->assertSame( + $originalExpiry->toDateTimeString(), + $reservation->expires_at->toDateTimeString() + ); + $this->assertSame( + $originalExpiry->toDateTimeString(), + $reservation->guaranteed_until->toDateTimeString() + ); + } + + public function test_admin_extension_is_capped_to_a_sixty_minute_short_hold_horizon(): void + { + Carbon::setTestNow('2026-07-27 12:00:00'); + + try { + $reservationId = $this->insertReservation(); + $token = (string) DB::table( + 'ptero_resource_reservations' + ) + ->where('id', $reservationId) + ->value('token'); + DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->update([ + 'expires_at' => now()->addMinutes(50), + 'guaranteed_until' => now()->addMinutes(50), + ]); + + $this->assertTrue($this->service()->extend($token, 30)); + + $reservation = ResourceReservation::query()->findOrFail( + $reservationId + ); + $maximum = now()->addMinutes(60); + $this->assertTrue( + $reservation->expires_at->equalTo($maximum) + ); + $this->assertTrue( + $reservation->guaranteed_until->equalTo($maximum) + ); + } finally { + Carbon::setTestNow(); + } + } + + public function test_admin_extension_cannot_modify_a_bound_guarantee(): void + { + $service = $this->makeService(); + $invoice = Invoice::factory()->create([ + 'user_id' => $service->user_id, + 'status' => Invoice::STATUS_PENDING, + 'currency_code' => 'USD', + ]); + $guaranteedUntil = now()->addDays(7); + $reservationId = $this->insertReservation( + serviceId: $service->id, + invoiceId: $invoice->id, + userId: $service->user_id, + guaranteedUntil: $guaranteedUntil + ); + $token = (string) DB::table('ptero_resource_reservations') + ->where('id', $reservationId) + ->value('token'); + + $this->assertFalse($this->service()->extend($token, 15)); + + $reservation = ResourceReservation::query()->findOrFail( + $reservationId + ); + $this->assertSame($service->id, $reservation->service_id); + $this->assertSame($invoice->id, $reservation->invoice_id); + $this->assertSame( + $guaranteedUntil->toDateTimeString(), + $reservation->guaranteed_until->toDateTimeString() + ); + } + + public function test_admin_extension_locks_rechecks_and_conditionally_updates(): void + { + $source = file_get_contents( + __DIR__.'/../../Services/ReservationService.php' + ); + $methodStart = strpos($source, 'public function extend('); + $methodEnd = strpos( + $source, + 'public function getByToken(', + $methodStart + ); + $method = substr( + $source, + $methodStart, + $methodEnd - $methodStart + ); + + $this->assertOrderedSourceMarkers($method, [ + 'DB::transaction(', + '->lockForUpdate()', + 'ResourceReservation::STATUS_PENDING', + "->whereNull('service_id')", + "->whereNull('invoice_id')", + '->update([', + ]); + } + public function test_reservation_snapshot_is_built_under_the_configuration_lock(): void { $source = file_get_contents( - __DIR__ . '/../../Services/ReservationService.php' + __DIR__.'/../../Services/ReservationService.php' ); $method = strpos( $source, @@ -338,7 +472,7 @@ public function test_reservation_snapshot_is_built_under_the_configuration_lock( public function test_checkout_binding_uses_global_capacity_invoice_lock_order(): void { $source = file_get_contents( - __DIR__ . '/../../Services/ReservationService.php' + __DIR__.'/../../Services/ReservationService.php' ); $method = strpos( $source, @@ -1754,6 +1888,116 @@ public function test_exact_guarantee_boundary_expires_order_and_blocks_payment() } } + public function test_cleanup_continues_after_corrupt_earlier_reservation(): void + { + $validService = $this->makeService(); + $paidInvoice = Invoice::factory()->create([ + 'user_id' => $validService->user_id, + 'status' => Invoice::STATUS_PAID, + 'due_at' => now()->subMinute(), + ]); + $corruptReservationId = $this->insertReservation( + invoiceId: $paidInvoice->id, + userId: $validService->user_id, + guaranteedUntil: now()->subMinute() + ); + $validReservationId = $this->insertReservation( + serviceId: $validService->id, + userId: $validService->user_id, + guaranteedUntil: now()->subMinute() + ); + $operatorAlerts = Mockery::mock(SchedulerOperatorAlertService::class); + $operatorAlerts->shouldReceive('notify') + ->once() + ->with(Mockery::on( + fn (array $context): bool => $context['entity_type'] + === 'resource_reservation' + && $context['entity_id'] === $corruptReservationId + )); + $this->app->instance( + SchedulerOperatorAlertService::class, + $operatorAlerts + ); + + $this->assertSame(1, $this->service()->cleanupExpired()); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $corruptReservationId, + 'status' => ResourceReservation::STATUS_PENDING, + ]); + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $validReservationId, + 'status' => ResourceReservation::STATUS_EXPIRED, + ]); + $this->assertSame( + Service::STATUS_CANCELLED, + $validService->fresh()->status + ); + } + + public function test_cleanup_cursor_reaches_valid_row_beyond_failed_page(): void + { + $validService = $this->makeService(); + $paidInvoice = Invoice::factory()->create([ + 'user_id' => $validService->user_id, + 'status' => Invoice::STATUS_PAID, + 'due_at' => now()->subMinute(), + ]); + $corruptReservationIds = []; + for ($index = 0; $index < 2; $index++) { + $corruptReservationIds[] = $this->insertReservation( + invoiceId: $paidInvoice->id, + userId: $validService->user_id, + guaranteedUntil: now()->subMinute() + ); + } + $validReservationId = $this->insertReservation( + serviceId: $validService->id, + userId: $validService->user_id, + guaranteedUntil: now()->subMinute() + ); + $operatorAlerts = Mockery::mock( + SchedulerOperatorAlertService::class + ); + $health = Mockery::mock( + SchedulerHealthService::class, + [$operatorAlerts] + )->makePartial(); + $health->shouldReceive('recordRowFailure')->times(2); + $this->app->instance(SchedulerHealthService::class, $health); + DB::table('ptero_scheduler_heartbeats') + ->where( + 'task_name', + SchedulerHealthService::TASK_EXPIRE_CHECKOUT + ) + ->update(['last_scanned_entity_id' => 0]); + + $this->assertSame(0, $this->service()->cleanupExpired(2)); + $this->assertSame(1, $this->service()->cleanupExpired(1)); + foreach ($corruptReservationIds as $corruptReservationId) { + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $corruptReservationId, + 'status' => ResourceReservation::STATUS_PENDING, + ]); + } + $this->assertDatabaseHas('ptero_resource_reservations', [ + 'id' => $validReservationId, + 'status' => ResourceReservation::STATUS_EXPIRED, + ]); + $this->assertSame( + $validReservationId, + (int) DB::table('ptero_scheduler_heartbeats') + ->where( + 'task_name', + SchedulerHealthService::TASK_EXPIRE_CHECKOUT + ) + ->value('last_scanned_entity_id') + ); + $this->assertSame( + Service::STATUS_CANCELLED, + $validService->fresh()->status + ); + } + public function test_late_gateway_payment_is_preserved_for_refund_review(): void { Carbon::setTestNow('2026-07-26 12:00:01'); @@ -2183,8 +2427,7 @@ public function test_mixed_paid_invoice_routes_only_the_row_backed_service_throu $reservationService->shouldReceive('commitPaidService') ->once() ->withArgs( - fn (Service $candidate, Invoice $paidInvoice): bool => - $candidate->is($dynamicService) && $paidInvoice->is($invoice) + fn (Service $candidate, Invoice $paidInvoice): bool => $candidate->is($dynamicService) && $paidInvoice->is($invoice) ) ->andReturnTrue(); $this->app->instance(ReservationService::class, $reservationService); @@ -2310,7 +2553,7 @@ public function test_allocation_row_drift_is_rejected_before_external_provisioni public function test_reconciler_recovers_a_stale_crashed_worker_lease(): void { - Bus::fake([CreateJob::class]); + Queue::fake(); $service = $this->makeService(status: 'provisioning'); $reservationId = $this->insertReservation( serviceId: $service->id, @@ -2325,10 +2568,16 @@ public function test_reconciler_recovers_a_stale_crashed_worker_lease(): void $this->assertNull($reservation->provisioning_started_at); $this->assertNull($reservation->provisioning_lease_id); $this->assertNotNull($reservation->next_provisioning_attempt_at); - Bus::assertDispatched( + Queue::assertPushed( CreateJob::class, - fn (CreateJob $job) => $job->service->is($service) + fn (CreateJob $job): bool => $job->service->is($service) + && $job->dispatchId !== null + && $job->dispatchToken !== null ); + $this->assertDatabaseHas('service_job_dispatches', [ + 'service_id' => $service->id, + 'action' => 'create', + ]); } public function test_fixed_port_is_claimed_before_an_earlier_wildcard_mapping(): void @@ -2372,6 +2621,25 @@ public function test_fixed_port_is_claimed_before_an_earlier_wildcard_mapping(): ], $mapped); } + /** + * @param array $markers + */ + private function assertOrderedSourceMarkers( + string $source, + array $markers + ): void { + $offset = 0; + + foreach ($markers as $marker) { + $position = strpos($source, $marker, $offset); + $this->assertNotFalse( + $position, + "Expected source marker [{$marker}] after offset {$offset}." + ); + $offset = $position + strlen($marker); + } + } + private function service(): ReservationService { $reflection = new \ReflectionClass(ReservationService::class); @@ -2661,13 +2929,11 @@ private function insertConfirmedCheckoutCommitment( $payload, JSON_THROW_ON_ERROR ), - 'configuration_fingerprint' => - $this->configurationService->fingerprint($payload), + 'configuration_fingerprint' => $this->configurationService->fingerprint($payload), 'paid_committed_at' => now()->subMonth(), 'external_server_id' => 71, 'external_user_id' => 44, - 'external_server_uuid' => - '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', + 'external_server_uuid' => '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', 'external_server_identifier' => 'created', 'updated_at' => now(), ]); @@ -2699,8 +2965,7 @@ private function cancellationServer(int $serviceId): array return [ 'attributes' => [ 'id' => 71, - 'uuid' => - '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', + 'uuid' => '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', 'identifier' => 'created', 'external_id' => (string) $serviceId, 'user' => 44, diff --git a/tests/Unit/ResourceCalculationServiceTest.php b/tests/Unit/ResourceCalculationServiceTest.php index 1ffb614..97c16ab 100644 --- a/tests/Unit/ResourceCalculationServiceTest.php +++ b/tests/Unit/ResourceCalculationServiceTest.php @@ -2,11 +2,15 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; +use App\Models\Invoice; +use App\Models\Plan; +use App\Models\Product; +use App\Models\Server; +use App\Models\Service; use App\Models\User; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\DB; use Mockery; -use PHPUnit\Framework\Attributes\DataProvider; use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\NodeCapacityPolicy; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\PterodactylInventoryService; @@ -14,6 +18,7 @@ use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceCalculationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\UpgradeReservationIntegrityService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; +use PHPUnit\Framework\Attributes\DataProvider; class ResourceCalculationServiceTest extends LaravelTestCase { @@ -303,7 +308,7 @@ public function test_upgrade_invoice_lifecycle_drift_fails_stock_closed(): void $this->assertNotNull($invoiceId); DB::table('invoices') ->where('id', $invoiceId) - ->update(['status' => \App\Models\Invoice::STATUS_PAID]); + ->update(['status' => Invoice::STATUS_PAID]); $this->expectException(InvalidStockConfigurationException::class); $this->expectExceptionMessage( @@ -316,11 +321,11 @@ public function test_upgrade_invoice_lifecycle_drift_fails_stock_closed(): void public function test_confirmed_checkout_stays_overlaid_until_same_snapshot_proves_target(): void { $this->createCpuPolicy(); - $serviceRecord = \App\Models\Service::factory()->create([ + $serviceRecord = Service::factory()->create([ 'user_id' => User::factory()->create()->id, ]); DB::table('services')->where('id', $serviceRecord->id)->update([ - 'status' => \App\Models\Service::STATUS_ACTIVE, + 'status' => Service::STATUS_ACTIVE, ]); $reservationId = $this->insertReservation( 'confirmed-checkout-overlay', @@ -334,8 +339,7 @@ public function test_confirmed_checkout_stays_overlaid_until_same_snapshot_prove 'purpose' => 'checkout', 'service_id' => $serviceRecord->id, 'external_server_id' => 81, - 'external_server_uuid' => - '10000000-0000-4000-8000-000000000081', + 'external_server_uuid' => '10000000-0000-4000-8000-000000000081', 'external_server_identifier' => 'server-81', 'consumed_at' => now(), ]); @@ -366,11 +370,11 @@ public function test_confirmed_checkout_stays_overlaid_until_same_snapshot_prove public function test_confirmed_upgrade_supersedes_checkout_and_overlays_only_snapshot_deficit(): void { $this->createCpuPolicy(); - $serviceRecord = \App\Models\Service::factory()->create([ + $serviceRecord = Service::factory()->create([ 'user_id' => User::factory()->create()->id, ]); DB::table('services')->where('id', $serviceRecord->id)->update([ - 'status' => \App\Models\Service::STATUS_ACTIVE, + 'status' => Service::STATUS_ACTIVE, ]); $checkoutId = $this->insertReservation( 'confirmed-checkout-before-upgrade', @@ -384,8 +388,7 @@ public function test_confirmed_upgrade_supersedes_checkout_and_overlays_only_sna 'purpose' => 'checkout', 'service_id' => $serviceRecord->id, 'external_server_id' => 81, - 'external_server_uuid' => - '10000000-0000-4000-8000-000000000081', + 'external_server_uuid' => '10000000-0000-4000-8000-000000000081', 'external_server_identifier' => 'server-81', 'consumed_at' => now()->subHour(), ]); @@ -435,11 +438,11 @@ public function test_confirmed_upgrade_supersedes_checkout_and_overlays_only_sna public function test_multiple_confirmed_upgrades_use_immutable_upgrade_order_not_mutable_timestamps(): void { $this->createCpuPolicy(); - $serviceRecord = \App\Models\Service::factory()->create([ + $serviceRecord = Service::factory()->create([ 'user_id' => User::factory()->create()->id, ]); DB::table('services')->where('id', $serviceRecord->id)->update([ - 'status' => \App\Models\Service::STATUS_ACTIVE, + 'status' => Service::STATUS_ACTIVE, ]); $checkoutId = $this->insertReservation( @@ -453,8 +456,7 @@ public function test_multiple_confirmed_upgrades_use_immutable_upgrade_order_not ->update([ 'service_id' => $serviceRecord->id, 'external_server_id' => 81, - 'external_server_uuid' => - '10000000-0000-4000-8000-000000000081', + 'external_server_uuid' => '10000000-0000-4000-8000-000000000081', 'external_server_identifier' => 'server-81', 'consumed_at' => now()->subHours(2), ]); @@ -499,11 +501,11 @@ public function test_multiple_confirmed_upgrades_use_immutable_upgrade_order_not public function test_conflicting_confirmed_server_identities_fail_snapshot_proof_closed(): void { $this->createCpuPolicy(); - $serviceRecord = \App\Models\Service::factory()->create([ + $serviceRecord = Service::factory()->create([ 'user_id' => User::factory()->create()->id, ]); DB::table('services')->where('id', $serviceRecord->id)->update([ - 'status' => \App\Models\Service::STATUS_ACTIVE, + 'status' => Service::STATUS_ACTIVE, ]); $checkoutId = $this->insertReservation( 'identity-checkout', @@ -576,11 +578,11 @@ public function test_server_assignment_wins_over_stale_node_allocation_snapshot( public function test_confirmed_local_claim_blocks_a_stale_free_allocation_snapshot(): void { $this->createCpuPolicy(); - $serviceRecord = \App\Models\Service::factory()->create([ + $serviceRecord = Service::factory()->create([ 'user_id' => User::factory()->create()->id, ]); DB::table('services')->where('id', $serviceRecord->id)->update([ - 'status' => \App\Models\Service::STATUS_ACTIVE, + 'status' => Service::STATUS_ACTIVE, ]); $reservationId = $this->insertReservation( 'confirmed-allocation-claim', @@ -992,9 +994,8 @@ public function test_signed_required_allocation_count_must_match_claim_set(): vo $payload, JSON_THROW_ON_ERROR ), - 'configuration_fingerprint' => - (new ReservationConfigurationService) - ->fingerprint($payload), + 'configuration_fingerprint' => (new ReservationConfigurationService) + ->fingerprint($payload), ]); $this->expectException(InvalidStockConfigurationException::class); @@ -1008,11 +1009,11 @@ public function test_signed_required_allocation_count_must_match_claim_set(): vo public function test_confirmed_dedicated_server_blocks_ip_until_service_is_cancelled(): void { $this->createCpuPolicy(); - $serviceRecord = \App\Models\Service::factory()->create([ + $serviceRecord = Service::factory()->create([ 'user_id' => User::factory()->create()->id, ]); DB::table('services')->where('id', $serviceRecord->id)->update([ - 'status' => \App\Models\Service::STATUS_ACTIVE, + 'status' => Service::STATUS_ACTIVE, ]); $reservationId = $this->insertReservation( 'confirmed-dedicated', @@ -1047,7 +1048,7 @@ public function test_confirmed_dedicated_server_blocks_ip_until_service_is_cance ); DB::table('services')->where('id', $serviceRecord->id)->update([ - 'status' => \App\Models\Service::STATUS_CANCELLED, + 'status' => Service::STATUS_CANCELLED, ]); $this->assertSame( [502, 503], @@ -1220,7 +1221,7 @@ private function insertUpgradeReservation( array $source, array $target, array $delta, - ?\App\Models\Service $service = null, + ?Service $service = null, int $externalServerId = 81, mixed $consumedAt = null ): int { @@ -1229,12 +1230,12 @@ private function insertUpgradeReservation( || $service->product_id === null || $service->plan_id === null ) { - $product = \App\Models\Product::factory()->create(); - $plan = \App\Models\Plan::factory()->create([ + $product = Product::factory()->create(); + $plan = Plan::factory()->create([ 'priceable_id' => $product->id, - 'priceable_type' => \App\Models\Product::class, + 'priceable_type' => Product::class, ]); - $service ??= \App\Models\Service::factory()->create([ + $service ??= Service::factory()->create([ 'user_id' => User::factory()->create()->id, ]); DB::table('services')->where('id', $service->id)->update([ @@ -1245,11 +1246,11 @@ private function insertUpgradeReservation( ]); $service->refresh(); } - $product = \App\Models\Product::query() + $product = Product::query() ->findOrFail($service->product_id); $server = $product->server; if ($server?->extension !== 'Pterodactyl') { - $server = \App\Models\Server::query()->create([ + $server = Server::query()->create([ 'name' => "Pterodactyl Upgrade {$token}", 'extension' => 'Pterodactyl', 'type' => 'server', @@ -1284,12 +1285,12 @@ private function insertUpgradeReservation( 'recurring_price' => '0.00', 'billing_anchor' => [], ]; - $invoice = \App\Models\Invoice::factory()->create([ + $invoice = Invoice::factory()->create([ 'user_id' => $service->user_id, 'status' => match ($status) { - 'pending' => \App\Models\Invoice::STATUS_PENDING, + 'pending' => Invoice::STATUS_PENDING, 'paid_committed', - 'confirmed' => \App\Models\Invoice::STATUS_PAID, + 'confirmed' => Invoice::STATUS_PAID, default => throw new \InvalidArgumentException( "Unsupported upgrade reservation status {$status}." ), @@ -1344,17 +1345,14 @@ private function insertUpgradeReservation( 'node_id' => 5, 'location_id' => 1, 'external_server_id' => $externalServerId, - 'external_server_uuid' => - sprintf( - '10000000-0000-4000-8000-%012d', - $externalServerId - ), - 'external_server_identifier' => - "server-{$externalServerId}", + 'external_server_uuid' => sprintf( + '10000000-0000-4000-8000-%012d', + $externalServerId + ), + 'external_server_identifier' => "server-{$externalServerId}", 'external_server_external_id' => (string) $service->id, 'external_user_id' => 44, - 'user_external_id' => - "paymenter-user-{$service->user_id}", + 'user_external_id' => "paymenter-user-{$service->user_id}", 'user_email' => (string) $service->user->email, 'nest_id' => 1, 'egg_id' => 2, @@ -1397,16 +1395,14 @@ private function insertUpgradeReservation( 'quantity' => 1, 'currency_code' => 'USD', 'panel_identity' => self::PANEL_IDENTITY, - 'configuration_fingerprint' => - (new UpgradeReservationIntegrityService) - ->fingerprint($upgrade, $payload), + 'configuration_fingerprint' => (new UpgradeReservationIntegrityService) + ->fingerprint($upgrade, $payload), 'configuration_payload' => json_encode( $payload, JSON_THROW_ON_ERROR ), - 'pricing_version' => - (new UpgradeReservationIntegrityService) - ->pricingVersion($upgrade), + 'pricing_version' => (new UpgradeReservationIntegrityService) + ->pricingVersion($upgrade), 'formula_version' => 'dynamic-upgrade-v1', 'node_id' => 5, 'location_id' => 1, @@ -1418,10 +1414,8 @@ private function insertUpgradeReservation( 'reserved_disk' => $delta['disk'], 'external_server_id' => $externalServerId, 'external_user_id' => 44, - 'external_server_uuid' => - $payload['external_server_uuid'], - 'external_server_identifier' => - $payload['external_server_identifier'], + 'external_server_uuid' => $payload['external_server_uuid'], + 'external_server_identifier' => $payload['external_server_identifier'], 'calculated_price' => '9.90', 'pricing_breakdown' => json_encode( [], @@ -1481,11 +1475,9 @@ private function insertReservation( } $allocation ??= [ - 'allocation_id' => - 100000 + (int) sprintf('%u', crc32($token)), + 'allocation_id' => 100000 + (int) sprintf('%u', crc32($token)), 'ip' => '198.51.100.10', - 'port' => - 20000 + ((int) sprintf('%u', crc32($token)) % 40000), + 'port' => 20000 + ((int) sprintf('%u', crc32($token)) % 40000), 'environment_key' => 'SERVER_PORT', 'is_primary' => true, ]; @@ -1509,9 +1501,8 @@ private function insertReservation( 'purpose' => $purpose, 'token' => $token, 'panel_identity' => $panelIdentity, - 'configuration_fingerprint' => - (new ReservationConfigurationService) - ->fingerprint($payload), + 'configuration_fingerprint' => (new ReservationConfigurationService) + ->fingerprint($payload), 'configuration_payload' => json_encode( $payload, JSON_THROW_ON_ERROR diff --git a/tests/Unit/ResourceQuoteServiceTest.php b/tests/Unit/ResourceQuoteServiceTest.php index 37515c0..889f463 100644 --- a/tests/Unit/ResourceQuoteServiceTest.php +++ b/tests/Unit/ResourceQuoteServiceTest.php @@ -4,7 +4,6 @@ use App\Models\Product; use Mockery; -use PHPUnit\Framework\Attributes\DataProvider; use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\InvalidStockConfigurationException; use Paymenter\Extensions\Others\DynamicPterodactyl\Exceptions\StockUnavailableException; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AllocationSelectionService; @@ -13,6 +12,7 @@ use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceCalculationService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceQuoteService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\TestCase; +use PHPUnit\Framework\Attributes\DataProvider; class ResourceQuoteServiceTest extends TestCase { @@ -110,7 +110,7 @@ public function test_quote_and_reservation_share_deterministic_multi_ip_port_sel ['id' => 101, 'ip' => '192.0.2.2', 'port' => 25570], ]; - $product = new Product(); + $product = new Product; $product->id = 99; $configurations = Mockery::mock(ProductResourceConfigurationService::class); $configurations->shouldReceive('forQuote') @@ -122,7 +122,7 @@ public function test_quote_and_reservation_share_deterministic_multi_ip_port_sel ->twice() ->with(1, null) ->andReturn(['nodes' => [$node]]); - $allocations = new AllocationSelectionService(); + $allocations = new AllocationSelectionService; $quote = (new ResourceQuoteService( $configurations, @@ -163,7 +163,7 @@ public function test_customer_quote_contains_no_node_identity(): void public function test_unbounded_inventory_is_configuration_failure(string $reason): void { $configuration = $this->configuration(); - $product = new Product(); + $product = new Product; $product->id = 99; $configurations = Mockery::mock(ProductResourceConfigurationService::class); $configurations->shouldReceive('forQuote')->andReturn($configuration); @@ -181,7 +181,7 @@ public function test_unbounded_inventory_is_configuration_failure(string $reason (new ResourceQuoteService( $configurations, $resources, - new AllocationSelectionService() + new AllocationSelectionService )) ->quote($product, []); } @@ -206,7 +206,7 @@ private function quote(array $requested, array $nodes): array private function runQuote(array $configuration, array $nodes): array { - $product = new Product(); + $product = new Product; $product->id = 99; $configurations = Mockery::mock(ProductResourceConfigurationService::class); $configurations->shouldReceive('forQuote') @@ -222,7 +222,7 @@ private function runQuote(array $configuration, array $nodes): array return (new ResourceQuoteService( $configurations, $resources, - new AllocationSelectionService() + new AllocationSelectionService )) ->quote($product, []); } diff --git a/tests/Unit/SchedulerHealthServiceTest.php b/tests/Unit/SchedulerHealthServiceTest.php new file mode 100644 index 0000000..55be417 --- /dev/null +++ b/tests/Unit/SchedulerHealthServiceTest.php @@ -0,0 +1,512 @@ +makePartial(); + $failure = new \RuntimeException('corrupt signed row'); + $health->shouldReceive('recordRowFailure') + ->once() + ->with( + SchedulerHealthService::TASK_EXPIRE_CHECKOUT, + 'resource_reservation', + 41, + $failure + ); + $visited = []; + + $processed = $health->processRows( + SchedulerHealthService::TASK_EXPIRE_CHECKOUT, + 'resource_reservation', + [41, 42, 43], + function (int $reservationId) use ( + &$visited, + $failure + ): bool { + $visited[] = $reservationId; + if ($reservationId === 41) { + throw $failure; + } + + return true; + } + ); + + $this->assertSame([41, 42, 43], $visited); + $this->assertSame(2, $processed); + } + + public function test_cursor_reaches_row_after_a_full_failed_page(): void + { + $candidateIds = $this->insertSchedulerCandidates(101); + $failedIds = array_fill_keys( + array_slice($candidateIds, 0, 100), + true + ); + $operatorAlerts = Mockery::mock( + SchedulerOperatorAlertService::class + ); + $health = Mockery::mock( + SchedulerHealthService::class, + [$operatorAlerts] + )->makePartial(); + $health->shouldReceive('recordRowFailure')->times(100); + $task = SchedulerHealthService::TASK_EXPIRE_CHECKOUT; + DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $task) + ->update(['last_scanned_entity_id' => 0]); + $eligible = fn () => DB::table('ptero_alert_configs') + ->where('location_name', 'like', 'scheduler-cursor-%'); + $firstVisited = []; + + $this->assertSame( + 0, + $health->processEligibleRows( + $task, + 'cursor_fixture', + 100, + $eligible, + function (int $candidateId) use ( + &$firstVisited, + $failedIds + ): bool { + $firstVisited[] = $candidateId; + if (isset($failedIds[$candidateId])) { + throw new \RuntimeException( + 'Deterministic corrupt row.' + ); + } + + return true; + } + ) + ); + $this->assertSame( + array_slice($candidateIds, 0, 100), + $firstVisited + ); + $this->assertSame( + $candidateIds[99], + (int) DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $task) + ->value('last_scanned_entity_id') + ); + + $secondVisited = []; + $this->assertSame( + 1, + $health->processEligibleRows( + $task, + 'cursor_fixture', + 100, + $eligible, + function (int $candidateId) use ( + &$secondVisited, + $candidateIds + ): bool { + $secondVisited[] = $candidateId; + + return $candidateId === $candidateIds[100]; + } + ) + ); + $this->assertSame($candidateIds[100], $secondVisited[0]); + } + + public function test_wrapped_scan_retries_a_repaired_early_row(): void + { + $candidateIds = $this->insertSchedulerCandidates(3); + $operatorAlerts = Mockery::mock( + SchedulerOperatorAlertService::class + ); + $health = Mockery::mock( + SchedulerHealthService::class, + [$operatorAlerts] + )->makePartial(); + $health->shouldReceive('recordRowFailure')->times(2); + $task = SchedulerHealthService::TASK_EXPIRE_CHECKOUT; + DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $task) + ->update(['last_scanned_entity_id' => 0]); + $eligible = fn () => DB::table('ptero_alert_configs') + ->where('location_name', 'like', 'scheduler-cursor-%'); + $firstVisited = []; + + $this->assertSame( + 0, + $health->processEligibleRows( + $task, + 'cursor_fixture', + 2, + $eligible, + function (int $candidateId) use ( + &$firstVisited + ): bool { + $firstVisited[] = $candidateId; + throw new \RuntimeException( + 'Temporarily corrupt row.' + ); + } + ) + ); + $this->assertSame( + array_slice($candidateIds, 0, 2), + $firstVisited + ); + + $secondVisited = []; + $this->assertSame( + 1, + $health->processEligibleRows( + $task, + 'cursor_fixture', + 2, + $eligible, + function (int $candidateId) use ( + &$secondVisited, + $candidateIds + ): bool { + $secondVisited[] = $candidateId; + + return $candidateId === $candidateIds[0]; + } + ) + ); + $this->assertSame( + [$candidateIds[2], $candidateIds[0]], + $secondVisited + ); + $this->assertSame( + $candidateIds[0], + (int) DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $task) + ->value('last_scanned_entity_id') + ); + } + + public function test_migration_seeds_every_runtime_task_definition(): void + { + foreach ( + SchedulerHealthService::taskDefinitions() as $taskName => $definition + ) { + $this->assertDatabaseHas('ptero_scheduler_heartbeats', [ + 'task_name' => $taskName, + 'expected_interval_seconds' => $definition[ + 'expected_interval_seconds' + ], + 'lag_threshold_seconds' => $definition[ + 'lag_threshold_seconds' + ], + 'last_scanned_entity_id' => 0, + ]); + } + } + + public function test_partial_run_keeps_previous_success_and_row_identity(): void + { + Carbon::setTestNow('2026-07-27 12:00:00'); + $operatorAlerts = Mockery::mock( + SchedulerOperatorAlertService::class + ); + $operatorAlerts->shouldReceive('notify') + ->once() + ->with(Mockery::on( + fn (array $context): bool => $context['task'] + === SchedulerHealthService::TASK_EXPIRE_CHECKOUT + && $context['entity_type'] === 'resource_reservation' + && $context['entity_id'] === 501 + && $context['error'] === 'invalid reservation' + )); + $health = new SchedulerHealthService($operatorAlerts); + $task = SchedulerHealthService::TASK_EXPIRE_CHECKOUT; + + DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $task) + ->delete(); + + $this->assertSame(2, $health->run($task, fn (): int => 2)); + $healthy = DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $task) + ->first(); + $this->assertSame(2, (int) $healthy->last_processed_count); + $this->assertSame(0, (int) $healthy->last_failure_count); + $this->assertSame( + '2026-07-27 12:00:00', + Carbon::parse($healthy->last_succeeded_at)->toDateTimeString() + ); + + Carbon::setTestNow('2026-07-27 12:01:00'); + $this->assertSame( + 1, + $health->run( + $task, + fn (): int => $health->processRows( + $task, + 'resource_reservation', + [501, 502], + function (int $reservationId): bool { + if ($reservationId === 501) { + throw new \RuntimeException( + 'invalid reservation' + ); + } + + return true; + } + ) + ) + ); + + $partial = DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $task) + ->first(); + $context = json_decode( + (string) $partial->last_failure_context, + true, + 512, + JSON_THROW_ON_ERROR + ); + + $this->assertSame(1, (int) $partial->last_processed_count); + $this->assertSame(1, (int) $partial->last_failure_count); + $this->assertSame(1, (int) $partial->consecutive_failures); + $this->assertSame('invalid reservation', $partial->last_error); + $this->assertSame(501, $context['entity_id']); + $this->assertSame('resource_reservation', $context['entity_type']); + $this->assertSame( + '2026-07-27 12:00:00', + Carbon::parse($partial->last_succeeded_at)->toDateTimeString() + ); + $this->assertSame( + '2026-07-27 12:01:00', + Carbon::parse($partial->last_completed_at)->toDateTimeString() + ); + } + + public function test_lag_is_persisted_alerted_once_and_cleared_by_success(): void + { + Carbon::setTestNow('2026-07-27 12:00:00'); + $task = SchedulerHealthService::TASK_EXPIRE_CHECKOUT; + $operatorAlerts = Mockery::mock( + SchedulerOperatorAlertService::class + ); + $operatorAlerts->shouldReceive('notify') + ->once() + ->with(Mockery::on( + fn (array $context): bool => $context['kind'] + === 'scheduler_lag' + && $context['task'] === $task + && $context['lag_seconds'] === 301 + )); + $health = new SchedulerHealthService($operatorAlerts); + + foreach ( + SchedulerHealthService::taskDefinitions() as $taskName => $definition + ) { + DB::table('ptero_scheduler_heartbeats')->updateOrInsert( + ['task_name' => $taskName], + [ + 'expected_interval_seconds' => $definition[ + 'expected_interval_seconds' + ], + 'lag_threshold_seconds' => $definition[ + 'lag_threshold_seconds' + ], + 'last_succeeded_at' => $taskName === $task + ? now()->subSeconds(301) + : now(), + 'last_alerted_at' => null, + 'lag_detected_at' => null, + 'created_at' => now(), + 'updated_at' => now(), + ] + ); + } + + $this->assertSame(1, $health->checkForLag()); + $this->assertSame(1, $health->checkForLag()); + $this->assertNotNull( + DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $task) + ->value('lag_detected_at') + ); + + $health->run($task, fn (): int => 0); + + $heartbeat = DB::table('ptero_scheduler_heartbeats') + ->where('task_name', $task) + ->first(); + $this->assertNull($heartbeat->lag_detected_at); + $this->assertSame( + '2026-07-27 12:00:00', + Carbon::parse($heartbeat->last_succeeded_at)->toDateTimeString() + ); + } + + public function test_bad_capacity_config_does_not_suppress_later_config(): void + { + DB::table('ptero_alert_configs')->delete(); + DB::table('ptero_scheduler_heartbeats') + ->where( + 'task_name', + SchedulerHealthService::TASK_CAPACITY_ALERTS + ) + ->delete(); + $bad = AlertConfig::create([ + 'location_id' => 71, + 'location_name' => 'Broken', + 'email_notifications' => false, + 'webhook_notifications' => false, + 'cooldown_minutes' => 60, + 'is_active' => true, + ]); + $good = AlertConfig::create([ + 'location_id' => 72, + 'location_name' => 'Healthy', + 'email_notifications' => false, + 'webhook_notifications' => false, + 'cooldown_minutes' => 60, + 'is_active' => true, + ]); + $resources = Mockery::mock(ResourceCalculationService::class); + $resources->shouldReceive('getLocationAvailability') + ->once() + ->with(71) + ->andThrow(new \RuntimeException('panel payload invalid')); + $resources->shouldReceive('getLocationAvailability') + ->once() + ->with(72) + ->andReturn([ + 'location_id' => 72, + 'location_name' => 'Healthy', + 'total_capacity' => [ + 'memory' => 100, + 'cpu' => 100, + 'disk' => 100, + ], + 'total_available' => [ + 'memory' => 100, + 'cpu' => 100, + 'disk' => 100, + ], + ]); + $operatorAlerts = Mockery::mock( + SchedulerOperatorAlertService::class + ); + $operatorAlerts->shouldReceive('notify') + ->once() + ->with(Mockery::on( + fn (array $context): bool => $context['entity_type'] + === 'alert_config_location' + && $context['entity_id'] === ($bad->id.':71') + )); + $this->app->instance( + SchedulerHealthService::class, + new SchedulerHealthService($operatorAlerts) + ); + + $processed = (new AlertService($resources)) + ->checkCapacityAlerts(chunkSize: 1); + + $this->assertSame(2, $processed); + $this->assertDatabaseHas('ptero_alert_configs', [ + 'id' => $good->id, + 'is_active' => true, + ]); + $heartbeat = DB::table('ptero_scheduler_heartbeats') + ->where( + 'task_name', + SchedulerHealthService::TASK_CAPACITY_ALERTS + ) + ->first(); + $context = json_decode( + (string) $heartbeat->last_failure_context, + true, + 512, + JSON_THROW_ON_ERROR + ); + $this->assertSame(($bad->id.':71'), $context['entity_id']); + $this->assertSame('panel payload invalid', $heartbeat->last_error); + } + + public function test_operator_alert_retains_failed_row_identity(): void + { + Notification::fake(); + $admin = User::factory()->create(['role_id' => 1]); + $context = [ + 'kind' => 'row_failure', + 'task' => SchedulerHealthService::TASK_RECONCILE_UPGRADES, + 'entity_type' => 'service_upgrade', + 'entity_id' => 991, + 'error' => 'upgrade snapshot drifted', + ]; + + (new SchedulerOperatorAlertService)->notify($context); + + Notification::assertSentTo( + $admin, + SchedulerTaskFailureNotification::class, + fn (SchedulerTaskFailureNotification $notification): bool => $notification->context === $context + ); + } + + /** + * @return list + */ + private function insertSchedulerCandidates(int $count): array + { + DB::table('ptero_alert_configs')->delete(); + $rows = []; + foreach (range(1, $count) as $index) { + $rows[] = [ + 'location_name' => "scheduler-cursor-{$index}", + 'email_notifications' => false, + 'webhook_notifications' => false, + 'is_active' => true, + 'created_at' => now(), + 'updated_at' => now(), + ]; + } + DB::table('ptero_alert_configs')->insert($rows); + + return DB::table('ptero_alert_configs') + ->where('location_name', 'like', 'scheduler-cursor-%') + ->orderBy('id') + ->pluck('id') + ->map(fn ($id): int => (int) $id) + ->all(); + } +} diff --git a/tests/Unit/UpgradeReservationServiceTest.php b/tests/Unit/UpgradeReservationServiceTest.php index 42f6036..f9e7e97 100644 --- a/tests/Unit/UpgradeReservationServiceTest.php +++ b/tests/Unit/UpgradeReservationServiceTest.php @@ -14,13 +14,15 @@ use App\Models\Plan; use App\Models\Price; use App\Models\Product; +use App\Models\Server; use App\Models\Service; use App\Models\ServiceConfig; use App\Models\ServiceUpgrade; -use App\Models\Server; use App\Models\User; use App\Services\Service\CapacityServiceCreationCoordinator; +use App\Services\ServiceUpgrade\ServiceUpgradeMutationCoordinator; use App\Services\ServiceUpgrade\ServiceUpgradeService; +use Carbon\Carbon; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Queue; @@ -131,7 +133,7 @@ public function test_upgrade_fixture_starts_from_completed_paid_checkout(): void $this->assertSame(Invoice::STATUS_PAID, $invoice->status); $this->assertSame( $invoice->due_at->getTimestamp(), - \Carbon\Carbon::parse( + Carbon::parse( $reservation->guaranteed_until )->getTimestamp() ); @@ -391,8 +393,7 @@ public function test_real_upgrade_reservation_is_accepted_by_stock_calculation_a { $fixture = $this->fixture(); NodeCapacityPolicy::create([ - 'panel_identity' => - hash('sha256', 'https://panel.example'), + 'panel_identity' => hash('sha256', 'https://panel.example'), 'node_uuid' => 'node-1', 'node_id' => 1, 'location_id' => 1, @@ -619,7 +620,7 @@ public function test_dynamic_upgrade_rejects_non_resource_configuration_change() 'configs.configValue', ]); $upgrade->captureSnapshots(); - $upgrade->save(); + ServiceUpgradeMutationCoordinator::save($upgrade); $this->expectException(InvalidResourceSelectionException::class); $this->expectExceptionMessage( @@ -702,6 +703,10 @@ public function test_paid_upgrade_payload_is_verified_before_leasing(): void $this->assertNull( $reservation->fresh()->provisioning_lease_id ); + Queue::assertPushed( + UpgradeJob::class, + fn (UpgradeJob $job): bool => $job->serviceUpgrade->is($upgrade) + ); } public function test_tampered_upgrade_payload_is_rejected_before_payment(): void @@ -1030,6 +1035,47 @@ public function test_expiry_with_partial_payment_releases_delta_and_requires_att ); } + public function test_stale_provisioning_recovery_uses_core_lifecycle_coordinator(): void + { + Queue::fake(); + $fixture = $this->fixture(); + [$upgrade, $invoice] = $this->upgrade($fixture); + $reservation = $fixture->upgrades->reserveForUpgrade( + $upgrade, + $invoice->due_at + ); + DB::table('invoices')->where('id', $invoice->id)->update([ + 'status' => Invoice::STATUS_PAID, + ]); + + $this->assertTrue( + $fixture->upgrades->commitPaidUpgrade( + $upgrade, + $invoice->fresh() + ) + ); + $provisioningUpgrade = app(ServiceUpgradeService::class) + ->beginProvisioning($upgrade->fresh()); + $fixture->upgrades->beginProvisioning($provisioningUpgrade); + DB::table('service_upgrades') + ->where('id', $upgrade->id) + ->update([ + 'provisioning_started_at' => now()->subMinutes(11), + ]); + + $this->assertSame( + 1, + $fixture->upgrades->reconcileStalledUpgrades() + ); + $this->assertSame( + ServiceUpgrade::STATUS_RETRYABLE_FAILED, + $upgrade->fresh()->status + ); + $this->assertNull( + $reservation->fresh()->provisioning_lease_id + ); + } + private function fixture(): object { $user = User::factory()->create(); @@ -1209,8 +1255,7 @@ private function fixture(): object ]; usort( $configurationOptions, - fn (array $left, array $right): int => - $left['id'] <=> $right['id'] + fn (array $left, array $right): int => $left['id'] <=> $right['id'] ); $cartSelections = collect($configurationOptions) ->map(function (array $option) use ( @@ -1225,8 +1270,7 @@ private function fixture(): object 'option_id' => (int) $option['id'], 'option_name' => (string) $model->name, 'option_type' => (string) $option['type'], - 'option_env_variable' => - (string) $option['environment_key'], + 'option_env_variable' => (string) $option['environment_key'], 'value' => $option['value'], ]; }) @@ -1285,8 +1329,7 @@ private function fixture(): object 'resources' => $resourceValues, 'calculated_price' => $checkoutPrice, 'pricing_version' => $pricingVersion, - 'formula_version' => - ReservationConfigurationService::FORMULA_VERSION, + 'formula_version' => ReservationConfigurationService::FORMULA_VERSION, 'config_options' => $configurationOptions, 'allocation_requirements' => [ 'required_count' => 1, @@ -1345,19 +1388,16 @@ private function fixture(): object 'plan_id' => $plan->id, 'quantity' => 1, 'currency_code' => 'USD', - 'configuration_fingerprint' => - $checkoutConfiguration->fingerprint($checkoutPayload), + 'configuration_fingerprint' => $checkoutConfiguration->fingerprint($checkoutPayload), 'configuration_payload' => json_encode( $checkoutPayload, JSON_THROW_ON_ERROR ), 'pricing_version' => $pricingVersion, - 'formula_version' => - ReservationConfigurationService::FORMULA_VERSION, + 'formula_version' => ReservationConfigurationService::FORMULA_VERSION, 'external_server_id' => 99, 'external_user_id' => 44, - 'external_server_uuid' => - '10000000-0000-4000-8000-000000000099', + 'external_server_uuid' => '10000000-0000-4000-8000-000000000099', 'external_server_identifier' => 'server-99', 'last_reconciled_at' => $checkoutCompletedAt, 'consumed_at' => $checkoutCompletedAt, @@ -1499,7 +1539,7 @@ private function upgrade(object $fixture): array 'configs.configValue', ]); $upgrade->captureSnapshots(); - $upgrade->save(); + ServiceUpgradeMutationCoordinator::save($upgrade); $invoice->items()->create([ 'description' => 'Resource upgrade', 'price' => 100, @@ -1526,7 +1566,7 @@ private function recaptureUpgrade(ServiceUpgrade $upgrade): void 'configs.configValue', ]); $upgrade->captureSnapshots(); - $upgrade->save(); + ServiceUpgradeMutationCoordinator::save($upgrade); } private function option( From e59b73488ae3f7813a28189c9d74d0f2537fe62b Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 27 Jul 2026 20:36:47 +1000 Subject: [PATCH 49/95] chore: preserve branch metadata --- .opencode/cache/cortex-loop-compliance.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .opencode/cache/cortex-loop-compliance.json diff --git a/.opencode/cache/cortex-loop-compliance.json b/.opencode/cache/cortex-loop-compliance.json new file mode 100644 index 0000000..66c44e7 --- /dev/null +++ b/.opencode/cache/cortex-loop-compliance.json @@ -0,0 +1,18 @@ +{ + "endedAt": "2026-07-25T09:03:14.804Z", + "durationMs": 3150617, + "totalToolCalls": 465, + "cortexCalls": 0, + "verbs": { + "reads": 0, + "ingests": 0, + "reconsolidations": 0, + "skillRetrieve": 0, + "skillStore": 0, + "skillExecuted": 0, + "reason": 0 + }, + "gaps": [ + "NO-CORTEX: 465 tool calls over 3151s with zero cortex_* usage - prior context never consulted, nothing captured." + ] +} \ No newline at end of file From 7267576951178b1bd1c599c10af8363a9edede8e Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 27 Jul 2026 20:58:53 +1000 Subject: [PATCH 50/95] test: repair cross-repository lifecycle gate --- .../cross-repository-integration.yml | 6 +- .../LegacyReservationReadinessTest.php | 57 ++++- tests/Unit/AlertServiceTest.php | 38 +-- tests/Unit/ReservationServiceTest.php | 6 +- tests/Unit/UpgradeReservationServiceTest.php | 226 +++++++++++------- 5 files changed, 221 insertions(+), 112 deletions(-) diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml index 19d2650..f6d9d4e 100644 --- a/.github/workflows/cross-repository-integration.yml +++ b/.github/workflows/cross-repository-integration.yml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 5bcb23966d0801ec5059e205511c24af0f9a3276 + ref: 8a9e4849f131795f430869128231f7a193bb8dcc path: paymenter - name: Set up PHP @@ -86,7 +86,7 @@ jobs: uses: actions/checkout@v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 5bcb23966d0801ec5059e205511c24af0f9a3276 + ref: 8a9e4849f131795f430869128231f7a193bb8dcc path: paymenter - name: Set up PHP @@ -182,7 +182,7 @@ jobs: uses: actions/checkout@v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 5bcb23966d0801ec5059e205511c24af0f9a3276 + ref: 8a9e4849f131795f430869128231f7a193bb8dcc path: paymenter - name: Set up PHP diff --git a/tests/Feature/LegacyReservationReadinessTest.php b/tests/Feature/LegacyReservationReadinessTest.php index 9da32c3..346c1ea 100644 --- a/tests/Feature/LegacyReservationReadinessTest.php +++ b/tests/Feature/LegacyReservationReadinessTest.php @@ -4,6 +4,7 @@ use App\Models\ConfigOption; use App\Models\ConfigOptionProduct; +use App\Models\Currency; use App\Models\Invoice; use App\Models\Plan; use App\Models\Price; @@ -1309,6 +1310,15 @@ private function insertAllocation( private function insertCompleteUpgradeReservation(): int { + Currency::query()->firstOrCreate( + ['code' => 'USD'], + [ + 'name' => 'US Dollar', + 'prefix' => '$', + 'suffix' => '', + 'format' => '1,000.00', + ] + ); $panel = hash('sha256', 'https://panel.example.com'); $server = Server::create([ 'name' => 'Pterodactyl', @@ -1329,6 +1339,10 @@ private function insertCompleteUpgradeReservation(): int $plan = Plan::factory()->create([ 'priceable_id' => $product->id, 'priceable_type' => Product::class, + 'name' => 'Monthly', + 'billing_unit' => 'month', + 'billing_period' => 1, + 'type' => 'recurring', ]); foreach ([ 'location_ids' => [[3], 'array'], @@ -1363,6 +1377,16 @@ private function insertCompleteUpgradeReservation(): int 'cpu' => 200, 'disk' => 20480, ]; + $sourceRecurringPrice = number_format( + 10 + array_sum($source), + 2, + '.', + '' + ); + $pricingLedgerStartedAt = now()->startOfDay(); + $pricingPeriodEndsAt = $pricingLedgerStartedAt + ->copy() + ->addMonth(); $options = []; foreach ($source as $resource => $value) { $options[$resource] = $this->dynamicOption( @@ -1374,17 +1398,25 @@ private function insertCompleteUpgradeReservation(): int $product, $plan, $options, - $source + $source, + $sourceRecurringPrice, + $pricingLedgerStartedAt, + $pricingPeriodEndsAt ): Service { $service = Service::factory()->create([ 'user_id' => User::factory()->create()->id, 'product_id' => $product->id, 'plan_id' => $plan->id, 'status' => Service::STATUS_ACTIVE, - 'price' => 10, + 'price' => $sourceRecurringPrice, + 'period_base_price' => $sourceRecurringPrice, + 'current_period_price' => $sourceRecurringPrice, + 'pricing_ledger_started_at' => $pricingLedgerStartedAt, + 'pricing_ledger_verified_at' => now(), + 'billing_cycles_completed' => 1, 'quantity' => 1, 'currency_code' => 'USD', - 'expires_at' => now()->addMonth(), + 'expires_at' => $pricingPeriodEndsAt, ]); foreach ($source as $resource => $value) { $service->configs()->create([ @@ -1415,7 +1447,8 @@ private function insertCompleteUpgradeReservation(): int 'status' => 'awaiting_payment', 'active_service_guard_id' => $service->id, 'type' => 'config_options', - 'quoted_amount' => '100.00', + 'capacity_mode' => ServiceUpgrade::CAPACITY_MODE_DYNAMIC, + 'quoted_amount' => null, 'currency_code' => 'USD', 'credit_amount' => 0, 'provisioning_attempts' => 0, @@ -1440,10 +1473,21 @@ private function insertCompleteUpgradeReservation(): int 'configs.configValue', ]); $upgrade->captureSnapshots(); + $targetSnapshot = (array) $upgrade->target_snapshot; + $quotedAmount = (string) ( + $targetSnapshot['upgrade_price'] ?? '' + ); + $creditAmount = (string) ( + $targetSnapshot['credit_amount'] ?? '' + ); + $upgrade->forceFill([ + 'quoted_amount' => $quotedAmount, + 'credit_amount' => $creditAmount, + ]); ServiceUpgradeMutationCoordinator::save($upgrade); $invoice->items()->create([ 'description' => 'Resource upgrade', - 'price' => '100.00', + 'price' => $quotedAmount, 'quantity' => 1, 'reference_id' => $upgrade->id, 'reference_type' => ServiceUpgrade::class, @@ -1508,7 +1552,7 @@ private function insertCompleteUpgradeReservation(): int 'external_user_id' => 44, 'external_server_uuid' => '2f4f28b0-0f36-4e6b-a2aa-a686c3466696', 'external_server_identifier' => 'server-71', - 'calculated_price' => '100.00', + 'calculated_price' => $quotedAmount, 'pricing_version' => (new UpgradeReservationIntegrityService) ->pricingVersion($upgrade), 'formula_version' => 'dynamic-upgrade-v1', @@ -1575,6 +1619,7 @@ function ($query) use ($upgrade): void { ->where('id', $upgrade->service_id) ->update([ 'price' => $target['recurring_price'], + 'current_period_price' => $target['recurring_price'], 'updated_at' => now(), ]); } diff --git a/tests/Unit/AlertServiceTest.php b/tests/Unit/AlertServiceTest.php index b5cb250..735b95f 100644 --- a/tests/Unit/AlertServiceTest.php +++ b/tests/Unit/AlertServiceTest.php @@ -238,10 +238,15 @@ public function test_notify_shortfall_no_admins_logs_warning(): void public function test_capacity_alert_email_fans_out_to_all_admins(): void { - $recipientA = new class + $query = Mockery::mock(); + $user = Mockery::mock('alias:App\\Models\\User'); + + $recipientA = new class extends User { public int $id = 101; + public string $email = 'admin-a@example.com'; + public array $notifications = []; public function notify($notification): void @@ -250,10 +255,12 @@ public function notify($notification): void } }; - $recipientB = new class + $recipientB = new class extends User { public int $id = 202; + public string $email = 'admin-b@example.com'; + public array $notifications = []; public function notify($notification): void @@ -262,10 +269,7 @@ public function notify($notification): void } }; - $query = Mockery::mock(); $query->shouldReceive('get')->once()->andReturn(new Collection([$recipientA, $recipientB])); - - $user = Mockery::mock('alias:App\\Models\\User'); $user->shouldReceive('whereNotNull')->once()->with('role_id')->andReturn($query); $service = $this->makeService(); @@ -334,10 +338,15 @@ public function test_capacity_alert_email_logs_warning_when_no_recipients(): voi public function test_capacity_alert_email_uses_evaluated_location_for_global_scope(): void { - $recipient = new class + $query = Mockery::mock(); + $user = Mockery::mock('alias:App\\Models\\User'); + + $recipient = new class extends User { public int $id = 303; + public string $email = 'admin@example.com'; + public array $notifications = []; public function notify($notification): void @@ -346,10 +355,7 @@ public function notify($notification): void } }; - $query = Mockery::mock(); $query->shouldReceive('get')->once()->andReturn(new Collection([$recipient])); - - $user = Mockery::mock('alias:App\\Models\\User'); $user->shouldReceive('whereNotNull')->once()->with('role_id')->andReturn($query); $service = $this->makeService(); @@ -384,20 +390,27 @@ public function test_capacity_alert_email_logged_on_dispatch_failure(): void { Log::spy(); - $failingRecipient = new class + $query = Mockery::mock(); + $user = Mockery::mock('alias:App\\Models\\User'); + + $failingRecipient = new class extends User { public int $id = 7; + public string $email = 'failing-admin@example.com'; + public function notify($notification): void { throw new \RuntimeException('smtp down'); } }; - $healthyRecipient = new class + $healthyRecipient = new class extends User { public int $id = 8; + public string $email = 'healthy-admin@example.com'; + public array $notifications = []; public function notify($notification): void @@ -406,10 +419,7 @@ public function notify($notification): void } }; - $query = Mockery::mock(); $query->shouldReceive('get')->once()->andReturn(new Collection([$failingRecipient, $healthyRecipient])); - - $user = Mockery::mock('alias:App\\Models\\User'); $user->shouldReceive('whereNotNull')->once()->with('role_id')->andReturn($query); $service = $this->makeService(); diff --git a/tests/Unit/ReservationServiceTest.php b/tests/Unit/ReservationServiceTest.php index 8e8a03b..a256772 100644 --- a/tests/Unit/ReservationServiceTest.php +++ b/tests/Unit/ReservationServiceTest.php @@ -1632,7 +1632,7 @@ public function test_reservation_identity_guard_survives_mutable_product_classif $service->currency_code = 'AUD'; $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('Reservation-backed service identity'); + $this->expectExceptionMessage('capacity-aware fulfillment coordinator'); $service->save(); } @@ -1659,7 +1659,7 @@ public function test_reserved_panel_host_cannot_change_while_commitment_is_live( $host->value = 'https://different-panel.example.com'; $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('pinned by active capacity commitments'); + $this->expectExceptionMessage('pinned by active services or upgrade commitments'); $host->save(); } @@ -1831,7 +1831,7 @@ public function test_reservation_backed_service_cannot_be_hard_deleted(): void ); $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('retained as fulfillment records'); + $this->expectExceptionMessage('cannot be hard deleted'); $service->delete(); } diff --git a/tests/Unit/UpgradeReservationServiceTest.php b/tests/Unit/UpgradeReservationServiceTest.php index f9e7e97..92f21c2 100644 --- a/tests/Unit/UpgradeReservationServiceTest.php +++ b/tests/Unit/UpgradeReservationServiceTest.php @@ -9,6 +9,7 @@ use App\Models\Cart; use App\Models\ConfigOption; use App\Models\ConfigOptionProduct; +use App\Models\Currency; use App\Models\Invoice; use App\Models\InvoiceTransaction; use App\Models\Plan; @@ -20,6 +21,7 @@ use App\Models\ServiceUpgrade; use App\Models\User; use App\Services\Service\CapacityServiceCreationCoordinator; +use App\Services\Service\ServiceBillingAnchorMutationCoordinator; use App\Services\ServiceUpgrade\ServiceUpgradeMutationCoordinator; use App\Services\ServiceUpgrade\ServiceUpgradeService; use Carbon\Carbon; @@ -337,20 +339,11 @@ public function test_second_slider_upgrade_uses_current_service_without_rewritin $this->assertEquals($checkoutBefore, $checkoutAfterFirst); $fixture->service->refresh(); - [$secondUpgrade, $secondInvoice] = $this->upgrade($fixture); - foreach ([ + [$secondUpgrade, $secondInvoice] = $this->upgrade($fixture, [ 'memory' => 12288, 'cpu' => 200, 'disk' => 40960, - ] as $resource => $value) { - $secondUpgrade->configs() - ->where( - 'config_option_id', - $fixture->options[$resource]->id - ) - ->update(['slider_value' => $value]); - } - $this->recaptureUpgrade($secondUpgrade); + ]); $secondReservation = $fixture->upgrades->reserveForUpgrade( $secondUpgrade->fresh(), @@ -454,43 +447,28 @@ public function test_real_upgrade_reservation_is_accepted_by_stock_calculation_a public function test_unchanged_resource_vector_is_not_an_upgrade(): void { $fixture = $this->fixture(); - [$upgrade, $invoice] = $this->upgrade($fixture); - foreach ([ + [$upgrade] = $this->upgrade($fixture, [ 'memory' => 4096, 'cpu' => 200, 'disk' => 20480, - ] as $resource => $value) { - $upgrade->configs() - ->where('config_option_id', $fixture->options[$resource]->id) - ->update(['slider_value' => $value]); - } - $this->recaptureUpgrade($upgrade); + ]); $this->expectException(InvalidResourceSelectionException::class); $this->expectExceptionMessage('must change at least one'); $fixture->upgrades->reserveForUpgrade( $upgrade->fresh(), - $invoice->due_at + now()->addDays(7) ); } - public function test_checkout_identity_survives_product_and_customer_email_edits(): void + public function test_checkout_identity_survives_customer_email_edits(): void { $fixture = $this->fixture(); $checkoutEmail = strtolower((string) $fixture->user->email); $fixture->user->update([ 'email' => "renamed-{$fixture->user->id}@example.com", ]); - $fixture->product->settings()->updateOrCreate( - ['key' => 'nest_id'], - ['value' => 77, 'type' => 'integer', 'encrypted' => false] - ); - $fixture->product->settings()->updateOrCreate( - ['key' => 'egg_id'], - ['value' => 88, 'type' => 'integer', 'encrypted' => false] - ); - $fixture->service->unsetRelation('product'); $fixture->service->unsetRelation('user'); [$upgrade, $invoice] = $this->upgrade($fixture); @@ -505,6 +483,42 @@ public function test_checkout_identity_survives_product_and_customer_email_edits $this->assertSame($checkoutEmail, $payload['user_email']); } + public function test_active_checkout_blocks_product_identity_setting_edits(): void + { + $fixture = $this->fixture(); + + foreach ([ + 'nest_id' => 77, + 'egg_id' => 88, + ] as $key => $value) { + try { + $fixture->product->settings()->updateOrCreate( + ['key' => $key], + [ + 'value' => $value, + 'type' => 'integer', + 'encrypted' => false, + ] + ); + $this->fail( + "Expected the active checkout to protect {$key}." + ); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'product setting identity is required', + strtolower($exception->getMessage()) + ); + } + + $this->assertSame( + $key === 'nest_id' ? 1 : 2, + (int) $fixture->product->settings() + ->where('key', $key) + ->value('value') + ); + } + } + public function test_server_identity_drift_is_rejected_before_upgrade_reservation(): void { $mutations = [ @@ -601,26 +615,10 @@ public function test_paid_commit_transition_does_not_bypass_invoice_line_proof() public function test_dynamic_upgrade_rejects_non_resource_configuration_change(): void { $fixture = $this->fixture(); - [$upgrade, $invoice] = $this->upgrade($fixture); - $upgrade->configs()->create([ - 'config_option_id' => $fixture->select->id, - 'config_value_id' => $fixture->selectAlternate->id, - 'slider_value' => null, - ]); - $upgrade->unsetRelation('configs'); - $upgrade->load([ - 'service.product.server.settings', - 'service.product.settings', - 'service.configs.configOption', - 'service.configs.configValue', - 'product.server.settings', - 'product.settings', - 'plan.prices', - 'configs.configOption', - 'configs.configValue', - ]); - $upgrade->captureSnapshots(); - ServiceUpgradeMutationCoordinator::save($upgrade); + [$upgrade, $invoice] = $this->upgrade( + $fixture, + selectValueId: $fixture->selectAlternate->id + ); $this->expectException(InvalidResourceSelectionException::class); $this->expectExceptionMessage( @@ -922,17 +920,42 @@ public function test_tampered_invoice_line_is_cancelled_before_paid_transition() public function test_renewal_after_quote_invalidates_upgrade_before_payment(): void { $fixture = $this->fixture(); - $fixture->service->expires_at = now()->addDays(10); - $fixture->service->save(); + $fixture->service = app( + ServiceBillingAnchorMutationCoordinator::class + )->update($fixture->service, [ + 'expires_at' => now()->addDays(10), + ]); [$upgrade, $invoice] = $this->upgrade($fixture); $reservation = $fixture->upgrades->reserveForUpgrade( $upgrade, $invoice->due_at ); - // Simulate the current service renewing on its old resource vector. - $fixture->service->expires_at = now()->addDays(35); - $fixture->service->save(); + try { + app(ServiceBillingAnchorMutationCoordinator::class)->update( + $fixture->service, + ['expires_at' => now()->addDays(35)] + ); + $this->fail( + 'Expected the active upgrade to serialize renewal.' + ); + } catch (\RuntimeException $exception) { + $this->assertStringContainsString( + 'cannot change while an upgrade is active', + strtolower($exception->getMessage()) + ); + } + + // Model an internal fulfillment transition that changes the billing + // anchor after the quote despite that public guard. The extension must + // still fail closed if another coordinated path drifts it. + ServiceBillingAnchorMutationCoordinator::run( + $fixture->service, + function () use ($fixture): void { + $fixture->service->expires_at = now()->addDays(35); + $fixture->service->save(); + } + ); $failure = $fixture->upgrades->preflightPaidUpgrade( $upgrade, @@ -978,7 +1001,7 @@ public function test_add_payment_preserves_rejected_upgrade_attention_and_paymen ExtensionHelper::addPayment( $invoice->id, null, - '100.00', + (string) $upgrade->quoted_amount, transactionId: 'paid-but-stale-upgrade' ); @@ -1078,6 +1101,15 @@ public function test_stale_provisioning_recovery_uses_core_lifecycle_coordinator private function fixture(): object { + Currency::firstOrCreate( + ['code' => 'USD'], + [ + 'name' => 'US Dollar', + 'prefix' => '$', + 'suffix' => '', + 'format' => '1,000.00', + ] + ); $user = User::factory()->create(); $server = Server::create([ 'name' => 'Pterodactyl', @@ -1175,6 +1207,22 @@ private function fixture(): object 'hidden' => false, 'parent_id' => $select->id, ]); + foreach ([$selectChild, $selectAlternate] as $selectValue) { + $selectPlan = Plan::factory()->create([ + 'priceable_id' => $selectValue->id, + 'priceable_type' => ConfigOption::class, + 'name' => 'Monthly', + 'billing_unit' => 'month', + 'billing_period' => 1, + 'type' => 'recurring', + ]); + Price::factory()->create([ + 'plan_id' => $selectPlan->id, + 'price' => 0, + 'setup_fee' => 0, + 'currency_code' => 'USD', + ]); + } $resourceValues = [ 'memory' => 4096, @@ -1497,26 +1545,26 @@ private function fixture(): object ]; } - private function upgrade(object $fixture): array - { + /** + * @param array{memory: int, cpu: int, disk: int}|null $resources + */ + private function upgrade( + object $fixture, + ?array $resources = null, + ?int $selectValueId = null + ): array { $dueAt = now()->addDays(7); - $invoice = Invoice::factory()->create([ - 'user_id' => $fixture->user->id, - 'currency_code' => 'USD', - 'status' => Invoice::STATUS_PENDING, - 'due_at' => $dueAt, - ]); $upgrade = ServiceUpgrade::create([ 'service_id' => $fixture->service->id, 'product_id' => $fixture->product->id, 'plan_id' => $fixture->plan->id, - 'invoice_id' => $invoice->id, + 'invoice_id' => null, 'status' => ServiceUpgrade::STATUS_AWAITING_PAYMENT, 'active_service_guard_id' => $fixture->service->id, - 'quoted_amount' => 100, 'currency_code' => 'USD', + 'capacity_mode' => ServiceUpgrade::CAPACITY_MODE_DYNAMIC, ]); - foreach ([ + foreach ($resources ?? [ 'memory' => 8192, 'cpu' => 100, 'disk' => 30720, @@ -1527,6 +1575,13 @@ private function upgrade(object $fixture): array 'slider_value' => $value, ]); } + if ($selectValueId !== null) { + $upgrade->configs()->create([ + 'config_option_id' => $fixture->select->id, + 'config_value_id' => $selectValueId, + 'slider_value' => null, + ]); + } $upgrade->load([ 'service.product.server.settings', 'service.product.settings', @@ -1539,36 +1594,35 @@ private function upgrade(object $fixture): array 'configs.configValue', ]); $upgrade->captureSnapshots(); + $upgrade->quoted_amount = round( + (float) $upgrade->signedUpgradePrice()->price, + 2 + ); + $upgrade->credit_amount = $upgrade->signedCreditAmount(); ServiceUpgradeMutationCoordinator::save($upgrade); + if ((float) $upgrade->quoted_amount <= 0) { + return [$upgrade->fresh(), null]; + } + + $invoice = Invoice::factory()->create([ + 'user_id' => $fixture->user->id, + 'currency_code' => 'USD', + 'status' => Invoice::STATUS_PENDING, + 'due_at' => $dueAt, + ]); $invoice->items()->create([ 'description' => 'Resource upgrade', - 'price' => 100, + 'price' => $upgrade->quoted_amount, 'quantity' => 1, 'reference_id' => $upgrade->id, 'reference_type' => ServiceUpgrade::class, ]); + $upgrade->invoice_id = $invoice->id; + ServiceUpgradeMutationCoordinator::save($upgrade); return [$upgrade->fresh(), $invoice->fresh()]; } - private function recaptureUpgrade(ServiceUpgrade $upgrade): void - { - $upgrade->unsetRelations(); - $upgrade->load([ - 'service.product.server.settings', - 'service.product.settings', - 'service.configs.configOption', - 'service.configs.configValue', - 'product.server.settings', - 'product.settings', - 'plan.prices', - 'configs.configOption', - 'configs.configValue', - ]); - $upgrade->captureSnapshots(); - ServiceUpgradeMutationCoordinator::save($upgrade); - } - private function option( Product $product, string $resource, From 99bcf272a5d919b91b290ac698a219251fbd6f1c Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 27 Jul 2026 21:03:50 +1000 Subject: [PATCH 51/95] test: align lifecycle fixtures with core guards --- tests/Feature/LegacyReservationReadinessTest.php | 4 +++- tests/Feature/NormalizeDynamicOptionKeysMigrationTest.php | 2 +- tests/Unit/UpgradeReservationServiceTest.php | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/Feature/LegacyReservationReadinessTest.php b/tests/Feature/LegacyReservationReadinessTest.php index 346c1ea..d98106c 100644 --- a/tests/Feature/LegacyReservationReadinessTest.php +++ b/tests/Feature/LegacyReservationReadinessTest.php @@ -1443,7 +1443,7 @@ private function insertCompleteUpgradeReservation(): int 'service_id' => $service->id, 'product_id' => $service->product_id, 'plan_id' => $service->plan_id, - 'invoice_id' => $invoice->id, + 'invoice_id' => null, 'status' => 'awaiting_payment', 'active_service_guard_id' => $service->id, 'type' => 'config_options', @@ -1492,6 +1492,8 @@ private function insertCompleteUpgradeReservation(): int 'reference_id' => $upgrade->id, 'reference_type' => ServiceUpgrade::class, ]); + $upgrade->invoice_id = $invoice->id; + ServiceUpgradeMutationCoordinator::save($upgrade); $sourceFingerprint = (string) $upgrade->source_fingerprint; $targetFingerprint = (string) $upgrade->target_fingerprint; $upgradeId = (int) $upgrade->id; diff --git a/tests/Feature/NormalizeDynamicOptionKeysMigrationTest.php b/tests/Feature/NormalizeDynamicOptionKeysMigrationTest.php index 98247d1..c538b1b 100644 --- a/tests/Feature/NormalizeDynamicOptionKeysMigrationTest.php +++ b/tests/Feature/NormalizeDynamicOptionKeysMigrationTest.php @@ -197,7 +197,7 @@ public function test_later_malformed_metadata_blocks_every_planned_change(): voi ); DB::table('config_options') ->where('id', $options['cpu']->id) - ->update(['metadata' => '{"resource_type":']); + ->update(['metadata' => '[]']); try { $this->runMigration(); diff --git a/tests/Unit/UpgradeReservationServiceTest.php b/tests/Unit/UpgradeReservationServiceTest.php index 92f21c2..e30d8fd 100644 --- a/tests/Unit/UpgradeReservationServiceTest.php +++ b/tests/Unit/UpgradeReservationServiceTest.php @@ -732,7 +732,7 @@ public function test_tampered_upgrade_payload_is_rejected_before_payment(): void ); $this->assertStringContainsString( - 'immutable integrity', + 'changed after the upgrade was quoted', strtolower((string) $failure) ); $this->assertSame( From 06f80761620d7c9f538decd03e5398b65d35dbd0 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 27 Jul 2026 21:05:00 +1000 Subject: [PATCH 52/95] test: preserve upgrade integrity regressions --- tests/Unit/UpgradeReservationServiceTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/UpgradeReservationServiceTest.php b/tests/Unit/UpgradeReservationServiceTest.php index e30d8fd..4d4e55c 100644 --- a/tests/Unit/UpgradeReservationServiceTest.php +++ b/tests/Unit/UpgradeReservationServiceTest.php @@ -732,7 +732,7 @@ public function test_tampered_upgrade_payload_is_rejected_before_payment(): void ); $this->assertStringContainsString( - 'changed after the upgrade was quoted', + 'immutable integrity', strtolower((string) $failure) ); $this->assertSame( @@ -824,7 +824,7 @@ public function test_server_extension_drift_is_rejected_before_payment(): void ); $this->assertStringContainsString( - 'immutable integrity', + 'changed after the upgrade was quoted', strtolower((string) $failure) ); $this->assertSame( From 7c8572008a991c546f3f4b2a2f5cfef6c8ffc26c Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Mon, 27 Jul 2026 21:10:52 +1000 Subject: [PATCH 53/95] fix: decouple local cancellation from panel credentials --- Services/PterodactylInventoryService.php | 23 +++++++++++++++---- .../Unit/PterodactylInventoryServiceTest.php | 14 +++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/Services/PterodactylInventoryService.php b/Services/PterodactylInventoryService.php index 1eb79a6..97c05be 100644 --- a/Services/PterodactylInventoryService.php +++ b/Services/PterodactylInventoryService.php @@ -52,16 +52,18 @@ public function __construct(?array $config = null) FILTER_VALIDATE_BOOLEAN ); - if ($this->apiUrl === '' || $this->apiKey === '') { - throw new \RuntimeException('Pterodactyl inventory credentials are not configured.'); - } - if (filter_var($this->apiUrl, FILTER_VALIDATE_URL) === false) { + if ( + $this->apiUrl !== '' + && filter_var($this->apiUrl, FILTER_VALIDATE_URL) === false + ) { throw new \RuntimeException('The Pterodactyl inventory URL is invalid.'); } } public function panelIdentity(): string { + $this->assertConfigured(); + return PanelEndpointIdentity::hash($this->apiUrl); } @@ -78,6 +80,8 @@ public function hasExclusiveProvisioningControl(): bool */ public function assertExclusiveProvisioningControl(): void { + $this->assertConfigured(); + if (! $this->exclusiveProvisioningControl) { throw new \RuntimeException( 'Dynamic stock requires administrator-confirmed exclusive provisioning control ' @@ -872,6 +876,8 @@ private function paginatedResourceIdentity(mixed $resource): string private function get(string $path, array $query): array { + $this->assertConfigured(); + try { $response = Http::withHeaders([ 'Authorization' => 'Bearer '.$this->apiKey, @@ -917,6 +923,15 @@ private function get(string $path, array $query): array return $payload; } + private function assertConfigured(): void + { + if ($this->apiUrl === '' || $this->apiKey === '') { + throw new \RuntimeException( + 'Pterodactyl inventory credentials are not configured.' + ); + } + } + private function attributes(array $resource, string $expectedObject): array { $object = $resource['object'] ?? null; diff --git a/tests/Unit/PterodactylInventoryServiceTest.php b/tests/Unit/PterodactylInventoryServiceTest.php index cfabb55..6b8d3f5 100644 --- a/tests/Unit/PterodactylInventoryServiceTest.php +++ b/tests/Unit/PterodactylInventoryServiceTest.php @@ -45,6 +45,20 @@ public function test_panel_identity_preserves_case_sensitive_path(): void ); } + public function test_missing_credentials_fail_only_when_inventory_is_used(): void + { + $inventory = new PterodactylInventoryService([]); + + $this->assertFalse($inventory->hasExclusiveProvisioningControl()); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage( + 'Pterodactyl inventory credentials are not configured.' + ); + + $inventory->panelIdentity(); + } + public function test_nodes_are_paginated_and_location_is_filtered_locally(): void { Http::fake(function ($request) { From 020c463f2bd197da6f94154f82123ee25a524c10 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 02:18:19 +1000 Subject: [PATCH 54/95] ci: stabilize cross-repository integration --- .../cross-repository-integration.yml | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml index f6d9d4e..943ab8a 100644 --- a/.github/workflows/cross-repository-integration.yml +++ b/.github/workflows/cross-repository-integration.yml @@ -10,6 +10,10 @@ on: permissions: contents: read +env: + COMPOSER_MAX_PARALLEL_HTTP: 1 + COMPOSER_PROCESS_TIMEOUT: 900 + concurrency: group: dynamic-pterodactyl-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true @@ -44,7 +48,12 @@ jobs: - name: Install Paymenter dependencies working-directory: paymenter - run: composer install --no-interaction --no-ansi --prefer-dist --no-progress + run: | + for attempt in 1 2 3 4; do + composer install --no-interaction --no-ansi --prefer-dist --no-progress && exit 0 + test "$attempt" -eq 4 && exit 1 + sleep $((attempt * 20)) + done - name: Audit Composer dependencies working-directory: paymenter @@ -99,7 +108,12 @@ jobs: - name: Install Paymenter dependencies working-directory: paymenter - run: composer install --prefer-dist --no-progress --no-suggest + run: | + for attempt in 1 2 3 4; do + composer install --no-interaction --prefer-dist --no-progress && exit 0 + test "$attempt" -eq 4 && exit 1 + sleep $((attempt * 20)) + done - name: Assemble extension checkout run: | @@ -134,7 +148,7 @@ jobs: env: APP_ENV: testing DB_CONNECTION: sqlite - DB_DATABASE: database/paymenter_test.sqlite + DB_DATABASE: ':temporary:' run: vendor/bin/phpunit -c extensions/Others/DynamicPterodactyl/phpunit.xml - name: Run Paymenter provisioning seam tests on SQLite @@ -195,7 +209,12 @@ jobs: - name: Install Paymenter dependencies working-directory: paymenter - run: composer install --prefer-dist --no-progress --no-suggest + run: | + for attempt in 1 2 3 4; do + composer install --no-interaction --prefer-dist --no-progress && exit 0 + test "$attempt" -eq 4 && exit 1 + sleep $((attempt * 20)) + done - name: Assemble extension checkout run: | From 69c9f0129f39c01f2776c3654d44754a1ba23d0b Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 02:34:27 +1000 Subject: [PATCH 55/95] test: isolate sqlite child processes --- tests/LaravelTestCase.php | 5 +++-- tests/Unit/TestDatabaseGuardTest.php | 20 ++++++++++++++++++++ tests/bootstrap.php | 1 - 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/tests/LaravelTestCase.php b/tests/LaravelTestCase.php index e9c5562..30ab2dd 100644 --- a/tests/LaravelTestCase.php +++ b/tests/LaravelTestCase.php @@ -33,9 +33,10 @@ public function createApplication() $kernel = $app->make(Kernel::class); $kernel->bootstrap(); - $database = getenv('DB_DATABASE') ?: ($_ENV['DB_DATABASE'] ?? ''); + $database = $_ENV['DB_DATABASE'] ?? $_SERVER['DB_DATABASE'] ?? getenv('DB_DATABASE') ?: ''; + $connection = $_ENV['DB_CONNECTION'] ?? $_SERVER['DB_CONNECTION'] ?? getenv('DB_CONNECTION') ?: ''; if (! self::$standaloneSqliteMigrated - && (getenv('DB_CONNECTION') ?: ($_ENV['DB_CONNECTION'] ?? '')) === 'sqlite' + && $connection === 'sqlite' && $database !== ':memory:' ) { $kernel->call('migrate', [ diff --git a/tests/Unit/TestDatabaseGuardTest.php b/tests/Unit/TestDatabaseGuardTest.php index 95d6b9e..1386417 100644 --- a/tests/Unit/TestDatabaseGuardTest.php +++ b/tests/Unit/TestDatabaseGuardTest.php @@ -4,6 +4,8 @@ use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\TestCase; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\TestDatabaseGuard; +use PHPUnit\Framework\Attributes\PreserveGlobalState; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; class TestDatabaseGuardTest extends TestCase { @@ -86,4 +88,22 @@ public function test_rejects_pre_existing_disposable_database_directory(): void rmdir($databaseDirectory); } } + + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] + public function test_separate_process_reclaims_temporary_database_from_the_sentinel(): void + { + $connection = $_ENV['DB_CONNECTION'] ?? $_SERVER['DB_CONNECTION'] ?? getenv('DB_CONNECTION') ?: ''; + if ($connection !== 'sqlite') { + $this->markTestSkipped('The separate-process claim is specific to the SQLite harness.'); + } + + $database = $_ENV['DB_DATABASE'] ?? $_SERVER['DB_DATABASE'] ?? ''; + + $this->assertSame(':temporary:', getenv('DB_DATABASE')); + $this->assertMatchesRegularExpression( + '/^file:dynamic-pterodactyl-test-[a-f0-9]{32}\?mode=memory&cache=shared$/', + $database, + ); + } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index fea94a7..7bba23b 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -40,7 +40,6 @@ } if ($claimedDatabase !== $db) { - putenv("DB_DATABASE={$claimedDatabase}"); $_ENV['DB_DATABASE'] = $claimedDatabase; $_SERVER['DB_DATABASE'] = $claimedDatabase; } From 0d0b6169aaef5f44f311f82bae05bbf4060e63c3 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 02:36:30 +1000 Subject: [PATCH 56/95] ci: pin audited companion dependencies --- .github/workflows/cross-repository-integration.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml index 943ab8a..1f72961 100644 --- a/.github/workflows/cross-repository-integration.yml +++ b/.github/workflows/cross-repository-integration.yml @@ -35,7 +35,7 @@ jobs: uses: actions/checkout@v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 8a9e4849f131795f430869128231f7a193bb8dcc + ref: 4bab39fa1ee8ae471a104efda15dd1ac037f209e path: paymenter - name: Set up PHP @@ -80,6 +80,7 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: false + max-parallel: 1 matrix: php: - '8.3' @@ -95,7 +96,7 @@ jobs: uses: actions/checkout@v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 8a9e4849f131795f430869128231f7a193bb8dcc + ref: 4bab39fa1ee8ae471a104efda15dd1ac037f209e path: paymenter - name: Set up PHP @@ -164,6 +165,7 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: false + max-parallel: 1 matrix: php: - '8.3' @@ -196,7 +198,7 @@ jobs: uses: actions/checkout@v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 8a9e4849f131795f430869128231f7a193bb8dcc + ref: 4bab39fa1ee8ae471a104efda15dd1ac037f209e path: paymenter - name: Set up PHP From 32eeb8e4ec74d3f916b2d0bf8570a85bfb62e5c6 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 02:51:22 +1000 Subject: [PATCH 57/95] docs: reconcile preserved qoder wiki --- .../en/content/API Reference/API Reference.md | 152 +++-- .../Admin API Endpoints.md | 119 ++-- .../Capacity Monitoring Endpoints.md | 89 +-- .../Reservation Management Endpoints.md | 129 ++-- .../Availability Endpoints.md | 99 +-- .../Public API Endpoints/Pricing Endpoints.md | 69 +- .../Public API Endpoints.md | 127 ++-- .../Reservation Endpoints.md | 167 ++--- .../Architecture Overview.md | 587 ++++-------------- .../Companion Extension Pattern.md | 133 ++-- .../Data Consistency Model.md | 139 +++-- .../Cart Events and Listeners.md | 127 ++-- .../Complete Checkout Flow Integration.md | 177 +++--- .../Event Registration and Configuration.md | 121 ++-- .../Event-Driven Architecture.md | 153 ++--- .../Payment and Service Events.md | 153 ++--- .../Real-Time Integration Strategy.md | 107 ++-- .../Node Selection Service.md | 115 ++-- .../Reservation Service.md | 197 +++--- .../Resource Calculation Service.md | 81 +-- .../Service Layer Design.md | 123 ++-- .../Supporting Services.md | 117 ++-- .qoder/repowiki/en/content/Configuration.md | 147 +++-- .../Core Services/ConfigOptionSetupService.md | 137 ++-- .../en/content/Core Services/Core Services.md | 114 ++-- .../Core Services/NodeSelectionService.md | 85 +-- .../Core Services/ReservationService.md | 145 ++--- .../ResourceCalculationService.md | 95 +-- .../SliderConfigReaderService.md | 109 ++-- .../Resource Reservations Table.md | 145 ++--- .qoder/repowiki/en/content/Deployment.md | 180 +++--- .qoder/repowiki/en/content/Event System.md | 146 +++-- .qoder/repowiki/en/content/Getting Started.md | 132 ++-- .qoder/repowiki/en/content/Testing.md | 198 +++--- .qoder/repowiki/en/content/Troubleshooting.md | 179 +++--- .../repowiki/en/meta/repowiki-metadata.json | 2 +- 36 files changed, 2491 insertions(+), 2604 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index b44aa9d..c2ca664 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -1,19 +1,45 @@ # API Reference +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + +## Current API Contract + +The reconciled extension exposes two quote endpoints and four admin endpoints. +Product quotes are guest-safe web requests protected by CSRF and the configured +quote limiter. Upgrade quotes require the authenticated service owner. Admin +routes require an authenticated Paymenter panel user and the extension's admin +middleware. + +| Method and path | Access | +|---|---| +| `POST /api/dynamic-pterodactyl/products/{product}/resource-quote` | Guest-safe web session, throttled | +| `POST /api/dynamic-pterodactyl/services/{service}/upgrade-quote` | Authenticated owner, throttled | +| `GET /api/dynamic-pterodactyl/admin/reservations` | Admin | +| `POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel` | Admin | +| `GET /api/dynamic-pterodactyl/admin/capacity` | Admin | +| `GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes` | Admin | + +There are no standalone customer availability, pricing, reservation-create, +reservation-confirm, or reservation-extend endpoints. Customer quote failures +are generic; upstream bodies and internal exception messages are never returned. + +[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php) + + **Referenced Files in This Document** -- [routes/api.php](file://routes/api.php) -- [AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) -- [PricingController.php](file://Http/Controllers/Api/PricingController.php) -- [ReservationController.php](file://Http/Controllers/Api/ReservationController.php) -- [AdminCapacityController.php](file://Http/Controllers/Api/Admin/AdminCapacityController.php) -- [AdminReservationController.php](file://Http/Controllers/Api/Admin/AdminReservationController.php) -- [StoreReservationRequest.php](file://Http/Requests/StoreReservationRequest.php) -- [EnsureUserIsAdmin.php](file://Http/Middleware/EnsureUserIsAdmin.php) -- [ResourceReservationPolicy.php](file://Policies/ResourceReservationPolicy.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php) +- [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) +- [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) +- [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) +- [AdminCapacityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php) +- [AdminReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php) +- [StoreReservationRequest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php) +- [EnsureUserIsAdmin.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php) +- [ResourceReservationPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) ## Table of Contents @@ -56,10 +82,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](file://routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](file://routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -69,11 +95,11 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] - AdminReservationController: Lists and cancels reservations with filtering and pagination. **Section sources** -- [AvailabilityController.php:9-70](file://Http/Controllers/Api/AvailabilityController.php#L9-L70) -- [PricingController.php:12-157](file://Http/Controllers/Api/PricingController.php#L12-L157) -- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [AdminCapacityController.php:8-62](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) -- [AdminReservationController.php:9-75](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) +- [AvailabilityController.php:9-70](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L9-L70) +- [PricingController.php:12-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L12-L157) +- [ReservationController.php:13-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminCapacityController.php:8-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) +- [AdminReservationController.php:9-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) ## Architecture Overview The API integrates with Paymenter core models and services and with the Pterodactyl panel via HTTP. Services encapsulate business logic and data aggregation. @@ -98,13 +124,13 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](file://routes/api.php#L17-L22) -- [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L17-L22) +- [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) **Section sources** -- [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) ## Detailed Component Analysis @@ -115,9 +141,9 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](file://routes/api.php#L17-L40) -- [EnsureUserIsAdmin.php:9-22](file://Http/Middleware/EnsureUserIsAdmin.php#L9-L22) -- [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L17-L40) +- [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) +- [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) ### Rate Limiting - Availability and pricing: 30 requests per minute per client. @@ -125,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](file://routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L17-L40) ### Endpoints @@ -164,8 +190,8 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](file://routes/api.php#L17-L40) -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L17-L40) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing - POST /api/dynamic-pterodactyl/pricing/calculate @@ -203,9 +229,9 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](file://routes/api.php#L17-L22) -- [PricingController.php:24-157](file://Http/Controllers/Api/PricingController.php#L24-L157) -- [StoreReservationRequest.php:38-112](file://Http/Requests/StoreReservationRequest.php#L38-L112) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L17-L22) +- [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) +- [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) #### Reservations - POST /api/dynamic-pterodactyl/reservation @@ -287,11 +313,11 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:24-137](file://Http/Controllers/Api/ReservationController.php#L24-L137) -- [StoreReservationRequest.php:10-162](file://Http/Requests/StoreReservationRequest.php#L10-L162) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ResourceReservationPolicy.php:25-58](file://Policies/ResourceReservationPolicy.php#L25-L58) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L24-L30) +- [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) +- [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ResourceReservationPolicy.php:25-58](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L25-L58) #### Admin Capacity - GET /api/dynamic-pterodactyl/admin/capacity @@ -317,9 +343,9 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](file://routes/api.php#L32-L40) -- [AdminCapacityController.php:17-62](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L32-L40) +- [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) #### Admin Reservations - GET /api/dynamic-pterodactyl/admin/reservations @@ -352,9 +378,9 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](file://routes/api.php#L32-L40) -- [AdminReservationController.php:18-75](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L32-L40) +- [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) ## Dependency Analysis The controllers depend on services for business logic and data aggregation. The following diagram shows key dependencies between controllers and services. @@ -407,22 +433,22 @@ AdminReservationController --> ReservationService : "uses" ``` **Diagram sources** -- [AvailabilityController.php:9-20](file://Http/Controllers/Api/AvailabilityController.php#L9-L20) -- [PricingController.php:12-19](file://Http/Controllers/Api/PricingController.php#L12-L19) -- [ReservationController.php:13-22](file://Http/Controllers/Api/ReservationController.php#L13-L22) -- [AdminCapacityController.php:8-15](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L15) -- [AdminReservationController.php:9-16](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L16) -- [ResourceCalculationService.php:10-21](file://Services/ResourceCalculationService.php#L10-L21) -- [ReservationService.php:16-35](file://Services/ReservationService.php#L16-L35) +- [AvailabilityController.php:9-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L9-L20) +- [PricingController.php:12-19](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L12-L19) +- [ReservationController.php:13-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L22) +- [AdminCapacityController.php:8-15](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L15) +- [AdminReservationController.php:9-16](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L9-L16) +- [ResourceCalculationService.php:10-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L10-L21) +- [ReservationService.php:16-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L35) **Section sources** -- [AvailabilityController.php:9-20](file://Http/Controllers/Api/AvailabilityController.php#L9-L20) -- [PricingController.php:12-19](file://Http/Controllers/Api/PricingController.php#L12-L19) -- [ReservationController.php:13-22](file://Http/Controllers/Api/ReservationController.php#L13-L22) -- [AdminCapacityController.php:8-15](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L15) -- [AdminReservationController.php:9-16](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L16) -- [ResourceCalculationService.php:10-21](file://Services/ResourceCalculationService.php#L10-L21) -- [ReservationService.php:16-35](file://Services/ReservationService.php#L16-L35) +- [AvailabilityController.php:9-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L9-L20) +- [PricingController.php:12-19](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L12-L19) +- [ReservationController.php:13-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L22) +- [AdminCapacityController.php:8-15](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L15) +- [AdminReservationController.php:9-16](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L9-L16) +- [ResourceCalculationService.php:10-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L10-L21) +- [ReservationService.php:16-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L35) ## Performance Considerations - Real-time Pterodactyl API calls are made without caching to ensure accurate availability. @@ -446,11 +472,11 @@ Operational notes: - Reservation creation supports idempotency via Idempotency-Key header or request body field; duplicates return the existing active reservation. **Section sources** -- [PricingController.php:104-121](file://Http/Controllers/Api/PricingController.php#L104-L121) -- [ReservationController.php:49-59](file://Http/Controllers/Api/ReservationController.php#L49-L59) -- [AdminReservationController.php:51-73](file://Http/Controllers/Api/Admin/AdminReservationController.php#L51-L73) -- [AdminCapacityController.php:53-60](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L53-L60) -- [ResourceCalculationService.php:403-417](file://Services/ResourceCalculationService.php#L403-L417) +- [PricingController.php:104-121](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L104-L121) +- [ReservationController.php:49-59](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L49-L59) +- [AdminReservationController.php:51-73](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L51-L73) +- [AdminCapacityController.php:53-60](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L53-L60) +- [ResourceCalculationService.php:403-417](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L403-L417) ## Conclusion The Dynamic Pterodactyl extension exposes a focused set of APIs for availability, pricing, and reservation management with clear separation between customer-facing and admin-only capabilities. Customer endpoints provide safe, aggregate data while protecting sensitive node-level details. Admin endpoints enable operational visibility and control over capacity and reservations. Robust rate limiting, authorization, and idempotency mechanisms help ensure reliability and security. diff --git a/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md b/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md index 4581b92..cb301d5 100644 --- a/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Admin API Endpoints.md @@ -1,17 +1,20 @@ # Admin API Endpoints +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [api.php](file://routes/api.php) -- [EnsureUserIsAdmin.php](file://Http/Middleware/EnsureUserIsAdmin.php) -- [AdminCapacityController.php](file://Http/Controllers/Api/Admin/AdminCapacityController.php) -- [AdminReservationController.php](file://Http/Controllers/Api/Admin/AdminReservationController.php) -- [AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [ResourceReservationPolicy.php](file://Policies/ResourceReservationPolicy.php) -- [AdminApiTest.php](file://tests/Feature/AdminApiTest.php) +- [api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [EnsureUserIsAdmin.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php) +- [AdminCapacityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php) +- [AdminReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php) +- [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [ResourceReservationPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php) +- [AdminApiTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AdminApiTest.php) ## Table of Contents @@ -51,16 +54,16 @@ AvailCtrl --> RCalcSvc ``` **Diagram sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [EnsureUserIsAdmin.php:11-21](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L21) -- [AdminCapacityController.php:17-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) -- [AdminReservationController.php:18-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) -- [AvailabilityController.php:54-69](file://Http/Controllers/Api/AvailabilityController.php#L54-L69) -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [ReservationService.php:312-330](file://Services/ReservationService.php#L312-L330) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [EnsureUserIsAdmin.php:11-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L21) +- [AdminCapacityController.php:17-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) +- [AdminReservationController.php:18-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) +- [AvailabilityController.php:54-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L54-L69) +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [ReservationService.php:312-330](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L312-L330) **Section sources** -- [api.php:17-40](file://routes/api.php#L17-L40) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ## Core Components - Admin capacity endpoint returns a cluster snapshot including per-location summaries and per-node availability derived from Pterodactyl and pending reservations. @@ -77,10 +80,10 @@ Rate limiting: - Customer-facing endpoints: separate lower limits where applicable. **Section sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [EnsureUserIsAdmin.php:11-21](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L21) -- [ResourceReservationPolicy.php:14-23](file://Policies/ResourceReservationPolicy.php#L14-L23) -- [AdminApiTest.php:52-66](file://tests/Feature/AdminApiTest.php#L52-L66) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [EnsureUserIsAdmin.php:11-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L21) +- [ResourceReservationPolicy.php:14-23](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L23) +- [AdminApiTest.php:52-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AdminApiTest.php#L52-L66) ## Architecture Overview The admin API follows a layered design: @@ -111,10 +114,10 @@ C-->>A : {success,data{locations,generated_at,error}} ``` **Diagram sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [EnsureUserIsAdmin.php:11-21](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L21) -- [AdminCapacityController.php:17-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [EnsureUserIsAdmin.php:11-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L21) +- [AdminCapacityController.php:17-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) ## Detailed Component Analysis @@ -172,11 +175,11 @@ Notes: - The snapshot aggregates pending reservations into per-node reserved resources. **Section sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [AdminCapacityController.php:17-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) -- [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [AdminCapacityController.php:17-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) +- [ResourceCalculationService.php:426-450](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L450) ### Reservation Management: GET /api/dynamic-pterodactyl/admin/reservations - Purpose: List reservations with optional filters and pagination. @@ -221,10 +224,10 @@ Example response (success): } **Section sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [AdminReservationController.php:18-34](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L34) -- [ReservationService.php:312-330](file://Services/ReservationService.php#L312-L330) -- [ReservationService.php:407-429](file://Services/ReservationService.php#L407-L429) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [AdminReservationController.php:18-34](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L34) +- [ReservationService.php:312-330](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L312-L330) +- [ReservationService.php:407-429](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L407-L429) ### Reservation Management: POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel - Purpose: Cancel a pending reservation with an audit reason. @@ -251,9 +254,9 @@ Example responses: - Conflict: { "success": false, "message": "Only pending reservations can be cancelled (current status: confirmed)" } **Section sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [AdminReservationController.php:36-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L36-L74) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [AdminReservationController.php:36-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L36-L74) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) ### Availability Inspection: GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes - Purpose: Retrieve per-node availability details for a location to troubleshoot capacity issues. @@ -288,9 +291,9 @@ Example response (success): } **Section sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [AvailabilityController.php:54-69](file://Http/Controllers/Api/AvailabilityController.php#L54-L69) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [AvailabilityController.php:54-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L54-L69) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) ### Security and Access Control - Middleware: @@ -305,9 +308,9 @@ Example unauthorized behavior: - Authenticated non-admin receives 403 with JSON error. **Section sources** -- [EnsureUserIsAdmin.php:11-21](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L21) -- [ResourceReservationPolicy.php:14-23](file://Policies/ResourceReservationPolicy.php#L14-L23) -- [AdminApiTest.php:52-66](file://tests/Feature/AdminApiTest.php#L52-L66) +- [EnsureUserIsAdmin.php:11-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L21) +- [ResourceReservationPolicy.php:14-23](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L23) +- [AdminApiTest.php:52-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AdminApiTest.php#L52-L66) ### Data Models and Relationships - ResourceReservation model defines table, fillable fields, casts, and scopes for pending/expired reservations. @@ -349,10 +352,10 @@ RESOURCE_RESERVATION ||--o| SERVICE : "service_id" ``` **Diagram sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) **Section sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ## Dependency Analysis - Admin controllers depend on services: @@ -373,16 +376,16 @@ ReservationService --> DB ``` **Diagram sources** -- [AdminCapacityController.php:17-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) -- [AdminReservationController.php:18-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [AdminCapacityController.php:17-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) +- [AdminReservationController.php:18-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) **Section sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) ## Performance Considerations - Real-time data: Availability and capacity endpoints call Pterodactyl API without caching to ensure accuracy. @@ -410,10 +413,10 @@ Validation and errors: - Controllers wrap exceptions and return structured error responses. **Section sources** -- [EnsureUserIsAdmin.php:11-21](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L21) -- [AdminCapacityController.php:53-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L53-L61) -- [AdminReservationController.php:36-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L36-L74) -- [AvailabilityController.php:54-69](file://Http/Controllers/Api/AvailabilityController.php#L54-L69) +- [EnsureUserIsAdmin.php:11-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L21) +- [AdminCapacityController.php:53-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L53-L61) +- [AdminReservationController.php:36-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L36-L74) +- [AvailabilityController.php:54-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L54-L69) ## Conclusion The admin API provides secure, rate-limited access to critical system monitoring and management capabilities: diff --git a/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Capacity Monitoring Endpoints.md b/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Capacity Monitoring Endpoints.md index 11d99c9..c3f27a5 100644 --- a/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Capacity Monitoring Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Capacity Monitoring Endpoints.md @@ -1,13 +1,16 @@ # Capacity Monitoring Endpoints +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [routes/api.php](file://routes/api.php) -- [Http/Middleware/EnsureUserIsAdmin.php](file://Http/Middleware/EnsureUserIsAdmin.php) -- [Http/Controllers/Api/Admin/AdminCapacityController.php](file://Http/Controllers/Api/Admin/AdminCapacityController.php) -- [Http/Controllers/Api/AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) -- [Services/ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [tests/Feature/AdminApiTest.php](file://tests/Feature/AdminApiTest.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [Http/Middleware/EnsureUserIsAdmin.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php) +- [Http/Controllers/Api/Admin/AdminCapacityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php) +- [Http/Controllers/Api/AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [tests/Feature/AdminApiTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AdminApiTest.php) ## Table of Contents @@ -49,13 +52,13 @@ Rcs2 --> Ptero ``` **Diagram sources** -- [routes/api.php:32-40](file://routes/api.php#L32-L40) -- [Http/Controllers/Api/Admin/AdminCapacityController.php:17-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) -- [Http/Controllers/Api/AvailabilityController.php:54-69](file://Http/Controllers/Api/AvailabilityController.php#L54-L69) -- [Services/ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [Http/Controllers/Api/Admin/AdminCapacityController.php:17-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) +- [Http/Controllers/Api/AvailabilityController.php:54-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L54-L69) +- [Services/ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) **Section sources** -- [routes/api.php:17-40](file://routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ## Core Components - AdminCapacityController::summary: Returns a structured snapshot of capacity across all locations, mapping internal snapshots to location summaries and exposing generated_at timestamps and optional error fields. @@ -70,10 +73,10 @@ Key responsibilities: - Aggregation of node-level metrics into location-level summaries for admin consumption. **Section sources** -- [Http/Controllers/Api/Admin/AdminCapacityController.php:17-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) -- [Http/Controllers/Api/AvailabilityController.php:54-69](file://Http/Controllers/Api/AvailabilityController.php#L54-L69) -- [Services/ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [Http/Middleware/EnsureUserIsAdmin.php:11-21](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L21) +- [Http/Controllers/Api/Admin/AdminCapacityController.php:17-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) +- [Http/Controllers/Api/AvailabilityController.php:54-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L54-L69) +- [Services/ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [Http/Middleware/EnsureUserIsAdmin.php:11-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L21) ## Architecture Overview The capacity monitoring flow involves authenticated admin requests routed through middleware, invoking controllers that delegate to ResourceCalculationService for live data aggregation from Pterodactyl. Responses include success flags, data payloads, and error indicators where applicable. @@ -98,10 +101,10 @@ Ctrl-->>Admin : JSON {success, data{locations, generated_at, error}} ``` **Diagram sources** -- [routes/api.php:32-40](file://routes/api.php#L32-L40) -- [Http/Middleware/EnsureUserIsAdmin.php:11-21](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L21) -- [Http/Controllers/Api/Admin/AdminCapacityController.php:17-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) -- [Services/ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [Http/Middleware/EnsureUserIsAdmin.php:11-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L21) +- [Http/Controllers/Api/Admin/AdminCapacityController.php:17-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) +- [Services/ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) ## Detailed Component Analysis @@ -171,10 +174,10 @@ Usage Notes: - If error is present, investigate upstream Pterodactyl connectivity or rate limits. **Section sources** -- [routes/api.php:32-40](file://routes/api.php#L32-L40) -- [Http/Controllers/Api/Admin/AdminCapacityController.php:17-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) -- [Services/ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [tests/Feature/AdminApiTest.php:132-166](file://tests/Feature/AdminApiTest.php#L132-L166) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [Http/Controllers/Api/Admin/AdminCapacityController.php:17-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) +- [Services/ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [tests/Feature/AdminApiTest.php:132-166](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AdminApiTest.php#L132-L166) ### Endpoint: GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes Purpose: @@ -237,10 +240,10 @@ Usage Notes: - Review server_count to understand workload distribution. **Section sources** -- [routes/api.php:32-40](file://routes/api.php#L32-L40) -- [Http/Controllers/Api/AvailabilityController.php:54-69](file://Http/Controllers/Api/AvailabilityController.php#L54-L69) -- [Services/ResourceCalculationService.php:24-67](file://Services/ResourceCalculationService.php#L24-L67) -- [tests/Feature/AdminApiTest.php:177-200](file://tests/Feature/AdminApiTest.php#L177-L200) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [Http/Controllers/Api/AvailabilityController.php:54-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L54-L69) +- [Services/ResourceCalculationService.php:24-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L24-L67) +- [tests/Feature/AdminApiTest.php:177-200](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AdminApiTest.php#L177-L200) ### Data Model and Aggregation Logic ResourceCalculationService constructs cluster snapshots and per-location availability by: @@ -262,15 +265,15 @@ ReturnSnapshot --> End(["End"]) ``` **Diagram sources** -- [Services/ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [Services/ResourceCalculationService.php:246-289](file://Services/ResourceCalculationService.php#L246-L289) -- [Services/ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) +- [Services/ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [Services/ResourceCalculationService.php:246-289](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L246-L289) +- [Services/ResourceCalculationService.php:426-450](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L450) **Section sources** -- [Services/ResourceCalculationService.php:24-67](file://Services/ResourceCalculationService.php#L24-L67) -- [Services/ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [Services/ResourceCalculationService.php:246-289](file://Services/ResourceCalculationService.php#L246-L289) -- [Services/ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) +- [Services/ResourceCalculationService.php:24-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L24-L67) +- [Services/ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [Services/ResourceCalculationService.php:246-289](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L246-L289) +- [Services/ResourceCalculationService.php:426-450](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L450) ## Dependency Analysis The capacity monitoring endpoints depend on: @@ -291,13 +294,13 @@ Rcs --> Ptero["Pterodactyl API"] ``` **Diagram sources** -- [routes/api.php:32-40](file://routes/api.php#L32-L40) -- [Http/Controllers/Api/Admin/AdminCapacityController.php:17-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) -- [Http/Controllers/Api/AvailabilityController.php:54-69](file://Http/Controllers/Api/AvailabilityController.php#L54-L69) -- [Services/ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [Http/Controllers/Api/Admin/AdminCapacityController.php:17-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) +- [Http/Controllers/Api/AvailabilityController.php:54-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L54-L69) +- [Services/ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) **Section sources** -- [routes/api.php:32-40](file://routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) ## Performance Considerations - Real-time API approach: No caching of Pterodactyl responses ensures accurate availability but may increase latency under load. @@ -326,10 +329,10 @@ Diagnostic steps: - Validate locationId and node existence in Pterodactyl. **Section sources** -- [Http/Middleware/EnsureUserIsAdmin.php:11-21](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L21) -- [Http/Controllers/Api/Admin/AdminCapacityController.php:53-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L53-L61) -- [Http/Controllers/Api/AvailabilityController.php:54-69](file://Http/Controllers/Api/AvailabilityController.php#L54-L69) -- [Services/ResourceCalculationService.php:410-424](file://Services/ResourceCalculationService.php#L410-L424) +- [Http/Middleware/EnsureUserIsAdmin.php:11-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L21) +- [Http/Controllers/Api/Admin/AdminCapacityController.php:53-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L53-L61) +- [Http/Controllers/Api/AvailabilityController.php:54-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L54-L69) +- [Services/ResourceCalculationService.php:410-424](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L410-L424) ## Conclusion The capacity monitoring endpoints provide administrators with essential insights into system health and resource utilization across Pterodactyl clusters. The aggregate capacity endpoint offers high-level metrics for quick assessments, while the node-level availability endpoint enables deep dives into specific locations. Both endpoints enforce strict authentication and rate limiting to ensure secure and sustainable operation. By leveraging these APIs, administrators can proactively identify bottlenecks, manage capacity planning, and respond to resource exhaustion issues effectively. diff --git a/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Reservation Management Endpoints.md b/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Reservation Management Endpoints.md index dc31b67..fa8c19d 100644 --- a/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Reservation Management Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Admin API Endpoints/Reservation Management Endpoints.md @@ -1,17 +1,20 @@ # Reservation Management Endpoints +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [api.php](file://routes/api.php) -- [AdminReservationController.php](file://Http/Controllers/Api/Admin/AdminReservationController.php) -- [EnsureUserIsAdmin.php](file://Http/Middleware/EnsureUserIsAdmin.php) -- [ResourceReservationPolicy.php](file://Policies/ResourceReservationPolicy.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) -- [2026_04_22_000001_drop_released_from_reservation_status.php](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) -- [AdminApiTest.php](file://tests/Feature/AdminApiTest.php) -- [ReservationApiTest.php](file://tests/Feature/ReservationApiTest.php) +- [api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [AdminReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php) +- [EnsureUserIsAdmin.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php) +- [ResourceReservationPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) +- [2026_04_22_000001_drop_released_from_reservation_status.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) +- [AdminApiTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AdminApiTest.php) +- [ReservationApiTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php) ## Table of Contents @@ -46,14 +49,14 @@ E --> F["Database: ptero_resource_reservations"] ``` **Diagram sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [AdminReservationController.php:18-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) -- [ReservationService.php:312-330](file://Services/ReservationService.php#L312-L330) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [AdminReservationController.php:18-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) +- [ReservationService.php:312-330](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L312-L330) **Section sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [AdminReservationController.php:18-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) -- [EnsureUserIsAdmin.php:11-20](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L20) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [AdminReservationController.php:18-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) +- [EnsureUserIsAdmin.php:11-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L20) ## Core Components - AdminReservationController: Validates requests, applies filters, paginates results, and cancels reservations. @@ -68,11 +71,11 @@ Key responsibilities: - Cancellation: requires reason string; only pending reservations can be cancelled. **Section sources** -- [AdminReservationController.php:18-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) -- [ReservationService.php:312-330](file://Services/ReservationService.php#L312-L330) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [EnsureUserIsAdmin.php:11-20](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L20) -- [ResourceReservationPolicy.php:14-23](file://Policies/ResourceReservationPolicy.php#L14-L23) +- [AdminReservationController.php:18-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) +- [ReservationService.php:312-330](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L312-L330) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [EnsureUserIsAdmin.php:11-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L20) +- [ResourceReservationPolicy.php:14-23](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L23) ## Architecture Overview Administrative endpoints are protected by session-based authentication and an admin role check. Requests flow through middleware before reaching the controller, which delegates to the service layer for data access and business logic. The service uses Eloquent builders for filtering and pagination. @@ -98,9 +101,9 @@ Ctrl-->>Client : { success : true, data : {...} } ``` **Diagram sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [AdminReservationController.php:18-33](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L33) -- [ReservationService.php:312-330](file://Services/ReservationService.php#L312-L330) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [AdminReservationController.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L33) +- [ReservationService.php:312-330](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L312-L330) ## Detailed Component Analysis @@ -158,12 +161,12 @@ Example usage: - GET /api/dynamic-pterodactyl/admin/reservations?per_page=50 **Section sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [AdminReservationController.php:18-33](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L33) -- [ReservationService.php:312-330](file://Services/ReservationService.php#L312-L330) -- [EnsureUserIsAdmin.php:11-20](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L20) -- [ReservationApiTest.php:290-317](file://tests/Feature/ReservationApiTest.php#L290-L317) -- [AdminApiTest.php:68-99](file://tests/Feature/AdminApiTest.php#L68-L99) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [AdminReservationController.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L33) +- [ReservationService.php:312-330](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L312-L330) +- [EnsureUserIsAdmin.php:11-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L20) +- [ReservationApiTest.php:290-317](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L290-L317) +- [AdminApiTest.php:68-99](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AdminApiTest.php#L68-L99) ### Endpoint: POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel Purpose: @@ -202,10 +205,10 @@ Edge cases: - Race conditions where status changes between validation and update result in 409. **Section sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [AdminReservationController.php:36-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L36-L74) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [AdminApiTest.php:101-130](file://tests/Feature/AdminApiTest.php#L101-L130) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [AdminReservationController.php:36-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L36-L74) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [AdminApiTest.php:101-130](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AdminApiTest.php#L101-L130) ### Data Model: ptero_resource_reservations Fields relevant to reservations: @@ -234,9 +237,9 @@ Status transitions: - released was removed; any existing released rows migrated to cancelled. **Section sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-61](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L61) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-18](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L18) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L61) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-18](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L18) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ### Authentication and Authorization - Session-based authentication is enforced by the web and auth middleware. @@ -248,9 +251,9 @@ Practical implications: - Administrative endpoints require explicit admin role and are intended for operational interventions. **Section sources** -- [EnsureUserIsAdmin.php:11-20](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L20) -- [ResourceReservationPolicy.php:14-23](file://Policies/ResourceReservationPolicy.php#L14-L23) -- [AdminApiTest.php:52-66](file://tests/Feature/AdminApiTest.php#L52-L66) +- [EnsureUserIsAdmin.php:11-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L20) +- [ResourceReservationPolicy.php:14-23](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L23) +- [AdminApiTest.php:52-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AdminApiTest.php#L52-L66) ### Error Handling Patterns Common HTTP status codes: @@ -266,9 +269,9 @@ Error payloads: - Consistent structure with success flag and message for admin endpoints. **Section sources** -- [AdminReservationController.php:36-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L36-L74) -- [EnsureUserIsAdmin.php:11-20](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L20) -- [api.php:32-40](file://routes/api.php#L32-L40) +- [AdminReservationController.php:36-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L36-L74) +- [EnsureUserIsAdmin.php:11-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L20) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) ## Dependency Analysis Administrative endpoints depend on: @@ -290,17 +293,17 @@ C --> P["ResourceReservationPolicy"] ``` **Diagram sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [AdminReservationController.php:18-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) -- [ReservationService.php:312-330](file://Services/ReservationService.php#L312-L330) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [EnsureUserIsAdmin.php:11-20](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L20) -- [ResourceReservationPolicy.php:14-23](file://Policies/ResourceReservationPolicy.php#L14-L23) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [AdminReservationController.php:18-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) +- [ReservationService.php:312-330](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L312-L330) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [EnsureUserIsAdmin.php:11-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L20) +- [ResourceReservationPolicy.php:14-23](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L23) **Section sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [AdminReservationController.php:18-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) -- [ReservationService.php:312-330](file://Services/ReservationService.php#L312-L330) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [AdminReservationController.php:18-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) +- [ReservationService.php:312-330](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L312-L330) ## Performance Considerations - Throttling: Admin routes are rate-limited at 30 requests per minute to protect backend resources. @@ -334,9 +337,9 @@ Operational tips: - During maintenance windows, extend TTLs via customer-facing extend endpoint if applicable; administrative cancellation is reserved for problematic cases. **Section sources** -- [AdminReservationController.php:36-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L36-L74) -- [AdminApiTest.php:52-66](file://tests/Feature/AdminApiTest.php#L52-L66) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) +- [AdminReservationController.php:36-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L36-L74) +- [AdminApiTest.php:52-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AdminApiTest.php#L52-L66) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) ## Conclusion The administrative reservation management endpoints provide robust tools for monitoring and intervening in the reservation lifecycle. They enforce strict authentication and authorization, support flexible filtering and pagination, and implement clear error handling patterns. Administrators can efficiently investigate issues, clean up problematic reservations, and maintain system stability during edge cases and maintenance. @@ -373,8 +376,8 @@ POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel - 422: Validation errors **Section sources** -- [AdminReservationController.php:18-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) -- [ReservationService.php:312-330](file://Services/ReservationService.php#L312-L330) +- [AdminReservationController.php:18-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) +- [ReservationService.php:312-330](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L312-L330) ### Common Administrative Workflows @@ -392,9 +395,9 @@ Handling edge cases during system maintenance: - Use administrative cancellation for problematic reservations that cannot proceed due to maintenance constraints. **Section sources** -- [AdminReservationController.php:18-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ReservationApiTest.php:290-317](file://tests/Feature/ReservationApiTest.php#L290-L317) +- [AdminReservationController.php:18-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ReservationApiTest.php:290-317](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L290-L317) ### Distinction Between Customer-Facing and Administrative Operations @@ -409,6 +412,6 @@ Administrative operations: - Intended for operational interventions and troubleshooting. **Section sources** -- [api.php:17-40](file://routes/api.php#L17-L40) -- [ResourceReservationPolicy.php:14-23](file://Policies/ResourceReservationPolicy.php#L14-L23) -- [AdminApiTest.php:168-200](file://tests/Feature/AdminApiTest.php#L168-L200) \ No newline at end of file +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [ResourceReservationPolicy.php:14-23](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L23) +- [AdminApiTest.php:168-200](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AdminApiTest.php#L168-L200) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md index e85607b..cbabf6e 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Availability Endpoints.md @@ -1,14 +1,17 @@ # Availability Endpoints +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [routes/api.php](file://routes/api.php) -- [AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) -- [NodeSelectionService.php](file://Services/NodeSelectionService.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [EnsureUserIsAdmin.php](file://Http/Middleware/EnsureUserIsAdmin.php) -- [AvailabilityApiTest.php](file://tests/Feature/AvailabilityApiTest.php) -- [DECISIONS.md](file://DECISIONS.md) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) +- [NodeSelectionService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [EnsureUserIsAdmin.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php) +- [AvailabilityApiTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AvailabilityApiTest.php) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md) ## Update Summary @@ -49,13 +52,13 @@ Security --> Response["Secure JSON Response
No Node Details"] ``` **Diagram sources** -- [routes/api.php:17-22](file://routes/api.php#L17-L22) -- [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [NodeSelectionService.php:78-97](file://Services/NodeSelectionService.php#L78-L97) -- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) +- [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [NodeSelectionService.php:78-97](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L78-L97) +- [ResourceCalculationService.php:23-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L23-L67) **Section sources** -- [routes/api.php:17-22](file://routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) ## Core Components - Route group: Defines the public availability endpoint and applies session-based authentication and rate limiting. @@ -72,10 +75,10 @@ Key responsibilities: - **Enhanced**: Ensure no node-level data leaks to customer responses through comprehensive testing and validation. **Section sources** -- [routes/api.php:17-22](file://routes/api.php#L17-L22) -- [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [NodeSelectionService.php:78-97](file://Services/NodeSelectionService.php#L78-L97) -- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) +- [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [NodeSelectionService.php:78-97](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L78-L97) +- [ResourceCalculationService.php:23-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L23-L67) ## Architecture Overview The GET /api/dynamic-pterodactyl/availability/{locationId} flow: @@ -108,10 +111,10 @@ A-->>C : {success, data : {location_id, max_memory, max_cpu, max_disk, node_coun ``` **Diagram sources** -- [routes/api.php:17-22](file://routes/api.php#L17-L22) -- [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [NodeSelectionService.php:78-97](file://Services/NodeSelectionService.php#L78-L97) -- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) +- [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [NodeSelectionService.php:78-97](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L78-L97) +- [ResourceCalculationService.php:23-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L23-L67) ## Detailed Component Analysis @@ -190,9 +193,9 @@ Why node-level details are not exposed - **Enhanced Security**: Comprehensive test coverage ensures that node-level data never leaks to customer responses through automated assertions. **Section sources** -- [routes/api.php:17-22](file://routes/api.php#L17-L22) -- [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [DECISIONS.md:237-239](file://DECISIONS.md#L237-L239) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) +- [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [DECISIONS.md:237-239](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L237-L239) ### Service Layer: Aggregation and Real-Time Data - NodeSelectionService::getMaxAvailable @@ -215,13 +218,13 @@ ForEachNode --> |No| ReturnData["Return {location_id, nodes[], max_available, to ``` **Diagram sources** -- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) +- [ResourceCalculationService.php:23-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L23-L67) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) **Section sources** -- [NodeSelectionService.php:78-97](file://Services/NodeSelectionService.php#L78-L97) -- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) +- [NodeSelectionService.php:78-97](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L78-L97) +- [ResourceCalculationService.php:23-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L23-L67) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) ### Middleware and Security - Web session and authentication: @@ -232,9 +235,9 @@ ForEachNode --> |No| ReturnData["Return {location_id, nodes[], max_available, to - Availability endpoints are limited to 30 requests per minute to protect the Pterodactyl API budget. **Section sources** -- [routes/api.php:17-22](file://routes/api.php#L17-L22) -- [routes/api.php:32-40](file://routes/api.php#L32-L40) -- [EnsureUserIsAdmin.php:9-21](file://Http/Middleware/EnsureUserIsAdmin.php#L9-L21) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [EnsureUserIsAdmin.php:9-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L21) ## Security and Data Exposure Prevention @@ -268,13 +271,13 @@ TestCoverage --> SecureResponse["Secure Response
(Aggregate only)"] ``` **Diagram sources** -- [AvailabilityApiTest.php:48-49](file://tests/Feature/AvailabilityApiTest.php#L48-L49) -- [AvailabilityApiTest.php:77-78](file://tests/Feature/AvailabilityApiTest.php#L77-L78) +- [AvailabilityApiTest.php:48-49](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AvailabilityApiTest.php#L48-L49) +- [AvailabilityApiTest.php:77-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AvailabilityApiTest.php#L77-L78) **Section sources** -- [AvailabilityApiTest.php:48-49](file://tests/Feature/AvailabilityApiTest.php#L48-L49) -- [AvailabilityApiTest.php:77-78](file://tests/Feature/AvailabilityApiTest.php#L77-L78) -- [DECISIONS.md:237-239](file://DECISIONS.md#L237-L239) +- [AvailabilityApiTest.php:48-49](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AvailabilityApiTest.php#L48-L49) +- [AvailabilityApiTest.php:77-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AvailabilityApiTest.php#L77-L78) +- [DECISIONS.md:237-239](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L237-L239) ## Dependency Analysis ```mermaid @@ -307,16 +310,16 @@ AvailabilityApiTest --> ResourceCalculationService : "mocks" ``` **Diagram sources** -- [AvailabilityController.php:9-20](file://Http/Controllers/Api/AvailabilityController.php#L9-L20) -- [NodeSelectionService.php:5-12](file://Services/NodeSelectionService.php#L5-L12) -- [ResourceCalculationService.php:10-21](file://Services/ResourceCalculationService.php#L10-L21) -- [AvailabilityApiTest.php:12-100](file://tests/Feature/AvailabilityApiTest.php#L12-L100) +- [AvailabilityController.php:9-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L9-L20) +- [NodeSelectionService.php:5-12](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L5-L12) +- [ResourceCalculationService.php:10-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L10-L21) +- [AvailabilityApiTest.php:12-100](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AvailabilityApiTest.php#L12-L100) **Section sources** -- [AvailabilityController.php:9-20](file://Http/Controllers/Api/AvailabilityController.php#L9-L20) -- [NodeSelectionService.php:5-12](file://Services/NodeSelectionService.php#L5-L12) -- [ResourceCalculationService.php:10-21](file://Services/ResourceCalculationService.php#L10-L21) -- [AvailabilityApiTest.php:12-100](file://tests/Feature/AvailabilityApiTest.php#L12-L100) +- [AvailabilityController.php:9-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L9-L20) +- [NodeSelectionService.php:5-12](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L5-L12) +- [ResourceCalculationService.php:10-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L10-L21) +- [AvailabilityApiTest.php:12-100](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AvailabilityApiTest.php#L12-L100) ## Performance Considerations - Real-time data fetching: @@ -353,10 +356,10 @@ Verification tips - **Enhanced**: Run security tests to verify no node-level data exposure in responses. **Section sources** -- [AvailabilityController.php:45-51](file://Http/Controllers/Api/AvailabilityController.php#L45-L51) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [AvailabilityApiTest.php:48-49](file://tests/Feature/AvailabilityApiTest.php#L48-L49) -- [AvailabilityApiTest.php:77-78](file://tests/Feature/AvailabilityApiTest.php#L77-L78) +- [AvailabilityController.php:45-51](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L45-L51) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [AvailabilityApiTest.php:48-49](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AvailabilityApiTest.php#L48-L49) +- [AvailabilityApiTest.php:77-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AvailabilityApiTest.php#L77-L78) ## Conclusion The GET /api/dynamic-pterodactyl/availability/{locationId} endpoint provides a secure, rate-limited, and real-time view of aggregate capacity for a given location. It exposes only what customers need to make purchasing decisions—maximum allocatable memory, CPU, and disk, along with a simple capacity indicator—while keeping node-level internals private. diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Pricing Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Pricing Endpoints.md index 97b1fce..a0416ab 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Pricing Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Pricing Endpoints.md @@ -1,14 +1,17 @@ # Pricing Endpoints +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [PricingController.php](file://Http/Controllers/Api/PricingController.php) -- [api.php](file://routes/api.php) -- [SliderConfigReaderService.php](file://Services/SliderConfigReaderService.php) -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [07-PRICING-MODELS.md](file://07-PRICING-MODELS.md) -- [02-SERVICES.md](file://02-SERVICES.md) -- [EnsureUserIsAdmin.php](file://Http/Middleware/EnsureUserIsAdmin.php) +- [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) +- [api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [SliderConfigReaderService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [07-PRICING-MODELS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/07-PRICING-MODELS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/02-SERVICES.md) +- [EnsureUserIsAdmin.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php) ## Table of Contents @@ -42,14 +45,14 @@ C --> F["Paymenter Core:
Plan::dynamicSliderBasePrice()
ConfigOption::ca ``` **Diagram sources** -- [DynamicPterodactyl.php:96-101](file://DynamicPterodactyl.php#L96-L101) -- [api.php:17-22](file://routes/api.php#L17-L22) -- [PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) -- [SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) +- [DynamicPterodactyl.php:96-101](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L101) +- [api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) +- [PricingController.php:24-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L145) +- [SliderConfigReaderService.php:14-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L53) **Section sources** -- [DynamicPterodactyl.php:96-101](file://DynamicPterodactyl.php#L96-L101) -- [api.php:17-22](file://routes/api.php#L17-L22) +- [DynamicPterodactyl.php:96-101](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L101) +- [api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) ## Core Components - PricingController: Validates input, resolves plan, computes per-slider deltas via core methods, aggregates totals, and returns breakdowns. @@ -62,9 +65,9 @@ Key responsibilities: - Consistent JSON response envelope with success/data or success/message/error fields. **Section sources** -- [PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) -- [SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) -- [api.php:17-22](file://routes/api.php#L17-L22) +- [PricingController.php:24-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L145) +- [SliderConfigReaderService.php:14-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L53) +- [api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) ## Architecture Overview The pricing flow is designed around delegation to Paymenter core. The controller validates and orchestrates, while core models perform the actual calculations. @@ -91,8 +94,8 @@ Note over FE,API : Throttled at 30 req/min with web+auth middleware ``` **Diagram sources** -- [PricingController.php:24-122](file://Http/Controllers/Api/PricingController.php#L24-L122) -- [api.php:17-22](file://routes/api.php#L17-L22) +- [PricingController.php:24-122](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L122) +- [api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) ## Detailed Component Analysis @@ -175,8 +178,8 @@ Frontend integration during checkout: - Step 3: Present total and per-slider breakdown to the user before proceeding to reservation creation. **Section sources** -- [PricingController.php:24-122](file://Http/Controllers/Api/PricingController.php#L24-L122) -- [api.php:17-22](file://routes/api.php#L17-L22) +- [PricingController.php:24-122](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L122) +- [api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) ### Endpoint: GET /api/dynamic-pterodactyl/pricing/config/{productId} Purpose: @@ -253,9 +256,9 @@ Concrete example: } **Section sources** -- [PricingController.php:127-145](file://Http/Controllers/Api/PricingController.php#L127-L145) -- [SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) -- [api.php:17-22](file://routes/api.php#L17-L22) +- [PricingController.php:127-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L127-L145) +- [SliderConfigReaderService.php:14-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L53) +- [api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) ### Pricing Ownership and Delegation This extension NEVER calculates prices directly. It: @@ -266,9 +269,9 @@ This extension NEVER calculates prices directly. It: This design ensures parity with checkout and renewal flows and centralizes pricing authority in Paymenter core. **Section sources** -- [07-PRICING-MODELS.md:19-27](file://07-PRICING-MODELS.md#L19-L27) -- [02-SERVICES.md:386-391](file://02-SERVICES.md#L386-L391) -- [PricingController.php:69-94](file://Http/Controllers/Api/PricingController.php#L69-L94) +- [07-PRICING-MODELS.md:19-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/07-PRICING-MODELS.md#L19-L27) +- [02-SERVICES.md:386-391](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/02-SERVICES.md#L386-L391) +- [PricingController.php:69-94](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L69-L94) ## Dependency Analysis The pricing endpoints depend on: @@ -315,12 +318,12 @@ PricingController --> ConfigOption : "calls core pricing" ``` **Diagram sources** -- [PricingController.php:12-157](file://Http/Controllers/Api/PricingController.php#L12-L157) -- [SliderConfigReaderService.php:7-66](file://Services/SliderConfigReaderService.php#L7-L66) +- [PricingController.php:12-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L12-L157) +- [SliderConfigReaderService.php:7-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L7-L66) **Section sources** -- [PricingController.php:12-157](file://Http/Controllers/Api/PricingController.php#L12-L157) -- [SliderConfigReaderService.php:7-66](file://Services/SliderConfigReaderService.php#L7-L66) +- [PricingController.php:12-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L12-L157) +- [SliderConfigReaderService.php:7-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L7-L66) ## Performance Considerations - Rate limiting: Both pricing endpoints are throttled to 30 requests per minute per client to protect downstream resources. @@ -350,9 +353,9 @@ Operational tips: - Check throttle limits if you see 429 responses during high-frequency testing. **Section sources** -- [PricingController.php:27-63](file://Http/Controllers/Api/PricingController.php#L27-L63) -- [PricingController.php:104-121](file://Http/Controllers/Api/PricingController.php#L104-L121) -- [api.php:17-22](file://routes/api.php#L17-L22) +- [PricingController.php:27-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L27-L63) +- [PricingController.php:104-121](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L104-L121) +- [api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) ## Conclusion The Dynamic Pterodactyl extension exposes two focused pricing endpoints that delegate all pricing math to Paymenter core. They provide: diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md index 6d8b5f5..8e1516c 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Public API Endpoints.md @@ -1,19 +1,22 @@ # Public API Endpoints +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [routes/api.php](file://routes/api.php) -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [Http/Controllers/Api/AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) -- [Http/Controllers/Api/PricingController.php](file://Http/Controllers/Api/PricingController.php) -- [Http/Controllers/Api/ReservationController.php](file://Http/Controllers/Api/ReservationController.php) -- [Http/Requests/StoreReservationRequest.php](file://Http/Requests/StoreReservationRequest.php) -- [Services/ReservationService.php](file://Services/ReservationService.php) -- [Models/ResourceReservation.php](file://Models/ResourceReservation.php) -- [Policies/ResourceReservationPolicy.php](file://Policies/ResourceReservationPolicy.php) -- [tests/Feature/AvailabilityApiTest.php](file://tests/Feature/AvailabilityApiTest.php) -- [tests/Feature/ReservationApiTest.php](file://tests/Feature/ReservationApiTest.php) -- [tests/Feature/PricingPreviewParityTest.php](file://tests/Feature/PricingPreviewParityTest.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [Http/Controllers/Api/AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) +- [Http/Controllers/Api/PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) +- [Http/Controllers/Api/ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) +- [Http/Requests/StoreReservationRequest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [Models/ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [Policies/ResourceReservationPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php) +- [tests/Feature/AvailabilityApiTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AvailabilityApiTest.php) +- [tests/Feature/ReservationApiTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php) +- [tests/Feature/PricingPreviewParityTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/PricingPreviewParityTest.php) ## Table of Contents @@ -56,15 +59,15 @@ ResSvc --> DB["Database (ptero_resource_reservations)"] ``` **Diagram sources** -- [routes/api.php:17-40](file://routes/api.php#L17-L40) -- [Http/Controllers/Api/AvailabilityController.php:9-20](file://Http/Controllers/Api/AvailabilityController.php#L9-L20) -- [Http/Controllers/Api/PricingController.php:12-19](file://Http/Controllers/Api/PricingController.php#L12-L19) -- [Http/Controllers/Api/ReservationController.php:13-22](file://Http/Controllers/Api/ReservationController.php#L13-L22) -- [Services/ReservationService.php:16-35](file://Services/ReservationService.php#L16-L35) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [Http/Controllers/Api/AvailabilityController.php:9-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L9-L20) +- [Http/Controllers/Api/PricingController.php:12-19](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L12-L19) +- [Http/Controllers/Api/ReservationController.php:13-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L22) +- [Services/ReservationService.php:16-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L35) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [routes/api.php:17-40](file://routes/api.php#L17-L40) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ## Core Components - AvailabilityController: Returns aggregate per-location capacity and whether all resources have capacity. @@ -75,13 +78,13 @@ ResSvc --> DB["Database (ptero_resource_reservations)"] - ResourceReservation model and policy: Define storage schema and authorization rules for viewing/canceling/extending. **Section sources** -- [Http/Controllers/Api/AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [Http/Controllers/Api/PricingController.php:24-122](file://Http/Controllers/Api/PricingController.php#L24-L122) -- [Http/Controllers/Api/ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [Http/Requests/StoreReservationRequest.php:38-113](file://Http/Requests/StoreReservationRequest.php#L38-L113) -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Models/ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [Policies/ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) +- [Http/Controllers/Api/AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [Http/Controllers/Api/PricingController.php:24-122](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L122) +- [Http/Controllers/Api/ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [Http/Requests/StoreReservationRequest.php:38-113](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L113) +- [Services/ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [Models/ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [Policies/ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) ## Architecture Overview The API is split into three protected groups: @@ -106,11 +109,11 @@ A-->>C : {success, data : {max_memory, max_cpu, max_disk, has_capacity, ...}} ``` **Diagram sources** -- [routes/api.php:17-22](file://routes/api.php#L17-L22) -- [Http/Controllers/Api/AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) +- [Http/Controllers/Api/AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) **Section sources** -- [routes/api.php:17-40](file://routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ## Detailed Component Analysis @@ -140,9 +143,9 @@ Implementation notes: - Errors return 500 with a generic message plus error only when applicable. **Section sources** -- [routes/api.php:17-22](file://routes/api.php#L17-L22) -- [Http/Controllers/Api/AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [tests/Feature/AvailabilityApiTest.php:23-73](file://tests/Feature/AvailabilityApiTest.php#L23-L73) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) +- [Http/Controllers/Api/AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [tests/Feature/AvailabilityApiTest.php:23-73](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AvailabilityApiTest.php#L23-L73) ### Pricing API - Base path: /api/dynamic-pterodactyl @@ -182,10 +185,10 @@ Notes: - Errors are logged; detailed error messages are included only when debug is enabled. **Section sources** -- [routes/api.php:17-22](file://routes/api.php#L17-L22) -- [Http/Controllers/Api/PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) -- [tests/Feature/PricingPreviewParityTest.php:25-79](file://tests/Feature/PricingPreviewParityTest.php#L25-L79) -- [tests/Feature/PricingPreviewParityTest.php:110-152](file://tests/Feature/PricingPreviewParityTest.php#L110-L152) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) +- [Http/Controllers/Api/PricingController.php:24-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L145) +- [tests/Feature/PricingPreviewParityTest.php:25-79](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/PricingPreviewParityTest.php#L25-L79) +- [tests/Feature/PricingPreviewParityTest.php:110-152](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/PricingPreviewParityTest.php#L110-L152) ### Reservation API - Base path: /api/dynamic-pterodactyl @@ -249,17 +252,17 @@ TTL and lifecycle: - After successful payment, reservations are confirmed and linked to a service. **Section sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [Http/Controllers/Api/ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [Http/Requests/StoreReservationRequest.php:38-113](file://Http/Requests/StoreReservationRequest.php#L38-L113) -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Services/ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) -- [Services/ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [Policies/ResourceReservationPolicy.php:28-69](file://Policies/ResourceReservationPolicy.php#L28-L69) -- [tests/Feature/ReservationApiTest.php:37-112](file://tests/Feature/ReservationApiTest.php#L37-L112) -- [tests/Feature/ReservationApiTest.php:179-247](file://tests/Feature/ReservationApiTest.php#L179-L247) -- [tests/Feature/ReservationApiTest.php:289-362](file://tests/Feature/ReservationApiTest.php#L289-L362) -- [tests/Feature/ReservationApiTest.php:375-400](file://tests/Feature/ReservationApiTest.php#L375-L400) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) +- [Http/Controllers/Api/ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [Http/Requests/StoreReservationRequest.php:38-113](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L113) +- [Services/ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [Services/ReservationService.php:166-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L281) +- [Services/ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [Policies/ResourceReservationPolicy.php:28-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L28-L69) +- [tests/Feature/ReservationApiTest.php:37-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L37-L112) +- [tests/Feature/ReservationApiTest.php:179-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L179-L247) +- [tests/Feature/ReservationApiTest.php:289-362](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L289-L362) +- [tests/Feature/ReservationApiTest.php:375-400](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L375-L400) ### Checkout Flow Integration Example Typical customer journey: @@ -292,8 +295,8 @@ Note over U,API : On payment success, system confirms reservation ``` **Diagram sources** -- [routes/api.php:17-30](file://routes/api.php#L17-L30) -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [routes/api.php:17-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L30) +- [Services/ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) ## Dependency Analysis - Availability depends on NodeSelectionService and ResourceCalculationService to compute aggregates and node counts. @@ -310,16 +313,16 @@ ResSvc --> Policy["ResourceReservationPolicy"] ``` **Diagram sources** -- [Http/Controllers/Api/AvailabilityController.php:9-20](file://Http/Controllers/Api/AvailabilityController.php#L9-L20) -- [Http/Controllers/Api/PricingController.php:12-19](file://Http/Controllers/Api/PricingController.php#L12-L19) -- [Http/Controllers/Api/ReservationController.php:13-22](file://Http/Controllers/Api/ReservationController.php#L13-L22) -- [Policies/ResourceReservationPolicy.php:9-23](file://Policies/ResourceReservationPolicy.php#L9-L23) +- [Http/Controllers/Api/AvailabilityController.php:9-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L9-L20) +- [Http/Controllers/Api/PricingController.php:12-19](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L12-L19) +- [Http/Controllers/Api/ReservationController.php:13-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L22) +- [Policies/ResourceReservationPolicy.php:9-23](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L23) **Section sources** -- [Http/Controllers/Api/AvailabilityController.php:9-20](file://Http/Controllers/Api/AvailabilityController.php#L9-L20) -- [Http/Controllers/Api/PricingController.php:12-19](file://Http/Controllers/Api/PricingController.php#L12-L19) -- [Http/Controllers/Api/ReservationController.php:13-22](file://Http/Controllers/Api/ReservationController.php#L13-L22) -- [Policies/ResourceReservationPolicy.php:9-23](file://Policies/ResourceReservationPolicy.php#L9-L23) +- [Http/Controllers/Api/AvailabilityController.php:9-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L9-L20) +- [Http/Controllers/Api/PricingController.php:12-19](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L12-L19) +- [Http/Controllers/Api/ReservationController.php:13-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L22) +- [Policies/ResourceReservationPolicy.php:9-23](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L23) ## Performance Considerations - Real-time availability: Pterodactyl API responses are not cached; availability is always fresh. Batching occurs internally to minimize calls. @@ -350,11 +353,11 @@ Error response patterns: - Reservation failures: 422 for validation/runtime errors; 404 for not found; 403 for unauthorized. **Section sources** -- [Http/Controllers/Api/AvailabilityController.php:45-52](file://Http/Controllers/Api/AvailabilityController.php#L45-L52) -- [Http/Controllers/Api/PricingController.php:104-121](file://Http/Controllers/Api/PricingController.php#L104-L121) -- [Http/Controllers/Api/ReservationController.php:62-136](file://Http/Controllers/Api/ReservationController.php#L62-L136) -- [Http/Requests/StoreReservationRequest.php:38-113](file://Http/Requests/StoreReservationRequest.php#L38-L113) -- [tests/Feature/ReservationApiTest.php:114-177](file://tests/Feature/ReservationApiTest.php#L114-L177) +- [Http/Controllers/Api/AvailabilityController.php:45-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L45-L52) +- [Http/Controllers/Api/PricingController.php:104-121](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L104-L121) +- [Http/Controllers/Api/ReservationController.php:62-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L62-L136) +- [Http/Requests/StoreReservationRequest.php:38-113](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L113) +- [tests/Feature/ReservationApiTest.php:114-177](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L114-L177) ## Conclusion The Dynamic Pterodactyl public API provides secure, rate-limited endpoints for checking availability, calculating dynamic pricing, and managing short-lived resource reservations during checkout. It exposes only aggregate capacity to customers, preserving node-level details for administrative use. The design emphasizes idempotency, real-time accuracy, and robust authorization to ensure safe and reliable integration with the checkout flow. diff --git a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Reservation Endpoints.md b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Reservation Endpoints.md index 31faf8d..46a357b 100644 --- a/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Reservation Endpoints.md +++ b/.qoder/repowiki/en/content/API Reference/Public API Endpoints/Reservation Endpoints.md @@ -1,17 +1,20 @@ # Reservation Endpoints +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [routes/api.php](file://routes/api.php) -- [ReservationController.php](file://Http/Controllers/Api/ReservationController.php) -- [StoreReservationRequest.php](file://Http/Requests/StoreReservationRequest.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [ResourceReservationPolicy.php](file://Policies/ResourceReservationPolicy.php) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) -- [2026_04_22_000001_drop_released_from_reservation_status.php](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) -- [ReservationApiTest.php](file://tests/Feature/ReservationApiTest.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) +- [StoreReservationRequest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [ResourceReservationPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) +- [2026_04_22_000001_drop_released_from_reservation_status.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) +- [ReservationApiTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php) ## Table of Contents @@ -47,13 +50,13 @@ Controller --> Policy["ResourceReservationPolicy"] ``` **Diagram sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [ReservationService.php:43-453](file://Services/ReservationService.php#L43-L453) -- [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) +- [ReservationController.php:13-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L137) +- [ReservationService.php:43-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L453) +- [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) **Section sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) ## Core Components - Routes: Define four reservation endpoints under a throttled, session-gated group. @@ -70,12 +73,12 @@ Key responsibilities: - Idempotency: Optional idempotency key prevents duplicate reservations. **Section sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [StoreReservationRequest.php:31-113](file://Http/Requests/StoreReservationRequest.php#L31-L113) -- [ReservationService.php:43-453](file://Services/ReservationService.php#L43-L453) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [StoreReservationRequest.php:31-113](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L31-L113) +- [ReservationService.php:43-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L453) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) ## Architecture Overview The reservation flow uses database transactions with pessimistic locking to avoid race conditions when selecting nodes and creating reservations. Idempotency is enforced through a unique constraint on active idempotency keys per user. Status transitions are strictly controlled by the service layer. @@ -99,12 +102,12 @@ Ctrl-->>C : 200 OK {success : true, data} ``` **Diagram sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:24-60](file://Http/Controllers/Api/ReservationController.php#L24-L60) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) +- [ReservationController.php:24-60](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L60) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) ## Detailed Component Analysis @@ -139,11 +142,11 @@ Example lifecycle step: - Client sends POST with product_id, location_id, and resource sliders; receives token and expires_at. **Section sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:24-60](file://Http/Controllers/Api/ReservationController.php#L24-L60) -- [StoreReservationRequest.php:31-113](file://Http/Requests/StoreReservationRequest.php#L31-L113) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationApiTest.php:37-78](file://tests/Feature/ReservationApiTest.php#L37-L78) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) +- [ReservationController.php:24-60](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L60) +- [StoreReservationRequest.php:31-113](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L31-L113) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationApiTest.php:37-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L37-L78) ### Endpoint: Get Reservation Status - Method: GET @@ -165,10 +168,10 @@ Example lifecycle step: - Client polls GET with token to check status before proceeding to payment confirmation. **Section sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:62-79](file://Http/Controllers/Api/ReservationController.php#L62-L79) -- [ResourceReservationPolicy.php:28-31](file://Policies/ResourceReservationPolicy.php#L28-L31) -- [ReservationApiTest.php:290-300](file://tests/Feature/ReservationApiTest.php#L290-L300) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) +- [ReservationController.php:62-79](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L62-L79) +- [ResourceReservationPolicy.php:28-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L28-L31) +- [ReservationApiTest.php:290-300](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L290-L300) ### Endpoint: Cancel Reservation - Method: DELETE @@ -190,11 +193,11 @@ Example lifecycle step: - Client cancels if user abandons checkout or explicitly opts out. **Section sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:81-100](file://Http/Controllers/Api/ReservationController.php#L81-L100) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ResourceReservationPolicy.php:37-40](file://Policies/ResourceReservationPolicy.php#L37-L40) -- [ReservationApiTest.php:302-317](file://tests/Feature/ReservationApiTest.php#L302-L317) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) +- [ReservationController.php:81-100](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L81-L100) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ResourceReservationPolicy.php:37-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L37-L40) +- [ReservationApiTest.php:302-317](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L302-L317) ### Endpoint: Extend Reservation TTL - Method: POST @@ -219,11 +222,11 @@ Example lifecycle step: - Client extends TTL during checkout delays to keep the reservation alive. **Section sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:102-136](file://Http/Controllers/Api/ReservationController.php#L102-L136) -- [ReservationService.php:250-281](file://Services/ReservationService.php#L250-L281) -- [ResourceReservationPolicy.php:45-48](file://Policies/ResourceReservationPolicy.php#L45-L48) -- [ReservationApiTest.php:319-329](file://tests/Feature/ReservationApiTest.php#L319-L329) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) +- [ReservationController.php:102-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L102-L136) +- [ReservationService.php:250-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L250-L281) +- [ResourceReservationPolicy.php:45-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L45-L48) +- [ReservationApiTest.php:319-329](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L319-L329) ### Request and Response Schemas @@ -264,9 +267,9 @@ Validation rules: - Idempotency key must match the allowed pattern. **Section sources** -- [StoreReservationRequest.php:31-113](file://Http/Requests/StoreReservationRequest.php#L31-L113) -- [ReservationService.php:407-429](file://Services/ReservationService.php#L407-L429) -- [ReservationApiTest.php:114-177](file://tests/Feature/ReservationApiTest.php#L114-L177) +- [StoreReservationRequest.php:31-113](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L31-L113) +- [ReservationService.php:407-429](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L407-L429) +- [ReservationApiTest.php:114-177](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L114-L177) ### Authentication and Authorization - Middleware: @@ -282,9 +285,9 @@ Security considerations: - Session-based auth: All endpoints require a web session; guests can create reservations but subsequent actions still require session context. **Section sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) -- [ReservationApiTest.php:290-362](file://tests/Feature/ReservationApiTest.php#L290-L362) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) +- [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) +- [ReservationApiTest.php:290-362](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L290-L362) ### Rate Limiting - Reservation endpoints are throttled to 10 requests per minute. @@ -295,9 +298,9 @@ Operational guidance: - Avoid rapid polling; batch status checks where possible. **Section sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationApiTest.php:249-271](file://tests/Feature/ReservationApiTest.php#L249-L271) -- [ReservationApiTest.php:375-400](file://tests/Feature/ReservationApiTest.php#L375-L400) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) +- [ReservationApiTest.php:249-271](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L249-L271) +- [ReservationApiTest.php:375-400](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L375-L400) ### Idempotency Support - Optional idempotency_key parameter or Idempotency-Key header. @@ -310,12 +313,12 @@ Implementation notes: - Database-level duplicate detection handled via exception inspection and fallback lookup. **Section sources** -- [StoreReservationRequest.php:31-36](file://Http/Requests/StoreReservationRequest.php#L31-L36) -- [ReservationService.php:60-73](file://Services/ReservationService.php#L60-L73) -- [ReservationService.php:143-157](file://Services/ReservationService.php#L143-L157) -- [ReservationService.php:431-452](file://Services/ReservationService.php#L431-L452) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-20](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L20) -- [ReservationApiTest.php:37-78](file://tests/Feature/ReservationApiTest.php#L37-L78) +- [StoreReservationRequest.php:31-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L31-L36) +- [ReservationService.php:60-73](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L60-L73) +- [ReservationService.php:143-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L143-L157) +- [ReservationService.php:431-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L431-L452) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L20) +- [ReservationApiTest.php:37-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L37-L78) ### State Machine Strict lifecycle: @@ -332,10 +335,10 @@ Why 'released' was removed: - Ensures clear end states for operational visibility and reporting. **Section sources** -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-18](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L18) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-18](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L18) ### Complete Lifecycle Examples @@ -356,10 +359,10 @@ Error scenarios: - Pterodactyl API failures: Node selection failure raises a runtime error; controller returns 422 with message. **Section sources** -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L281) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) ## Dependency Analysis The reservation subsystem depends on: @@ -379,16 +382,16 @@ Service --> DB["Database"] ``` **Diagram sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [StoreReservationRequest.php:10-162](file://Http/Requests/StoreReservationRequest.php#L10-L162) -- [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) -- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) +- [ReservationController.php:13-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L137) +- [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) +- [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) +- [ReservationService.php:16-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L453) **Section sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) +- [ReservationController.php:13-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L137) +- [ReservationService.php:16-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L453) ## Performance Considerations - Pessimistic locking: Uses lockForUpdate to prevent concurrent modifications during node selection and reservation creation. @@ -402,8 +405,8 @@ Recommendations: - Monitor database locks and adjust timeouts if necessary. **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:55-61](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L55-L61) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:55-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L55-L61) ## Troubleshooting Guide Common issues and resolutions: @@ -429,11 +432,11 @@ Operational tips: - Monitor scheduled cleanup jobs that mark expired reservations. **Section sources** -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [ReservationService.php:125-141](file://Services/ReservationService.php#L125-L141) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [ReservationApiTest.php:114-177](file://tests/Feature/ReservationApiTest.php#L114-L177) -- [ReservationApiTest.php:249-271](file://tests/Feature/ReservationApiTest.php#L249-L271) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [ReservationService.php:125-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L125-L141) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [ReservationApiTest.php:114-177](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L114-L177) +- [ReservationApiTest.php:249-271](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L249-L271) ## Conclusion The reservation endpoints provide a secure, rate-limited, and idempotent mechanism to manage the checkout lifecycle. They enforce strict state transitions, robust authorization, and resilient database operations. Clients should rely on tokens for access control, use idempotency keys for safe retries, and respect rate limits. The removal of the 'released' state simplifies the lifecycle and improves clarity for operational workflows. \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index c4e3e69..2a4a0f8 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,472 +2,139 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [DECISIONS.md](file://DECISIONS.md) -- [AGENTS.md](file://AGENTS.md) -- [routes/api.php](file://routes/api.php) -- [Services/ReservationService.php](file://Services/ReservationService.php) -- [Services/ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [Services/NodeSelectionService.php](file://Services/NodeSelectionService.php) -- [Listeners/CartItemCreatedListener.php](file://Listeners/CartItemCreatedListener.php) -- [Listeners/InvoicePaidListener.php](file://Listeners/InvoicePaidListener.php) -- [Http/Controllers/Api/AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) -- [Models/ResourceReservation.php](file://Models/ResourceReservation.php) -- [Policies/ResourceReservationPolicy.php](file://Policies/ResourceReservationPolicy.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Services/UpgradeReservationService.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Listeners/CartItemDeletedListener.php) -## Table of Contents -1. [Introduction](#introduction) -2. [Project Structure](#project-structure) -3. [Core Components](#core-components) -4. [Architecture Overview](#architecture-overview) -5. [Detailed Component Analysis](#detailed-component-analysis) -6. [Dependency Analysis](#dependency-analysis) -7. [Performance Considerations](#performance-considerations) -8. [Troubleshooting Guide](#troubleshooting-guide) -9. [Conclusion](#conclusion) +## Reconciled Architecture -## Introduction -This document describes the architecture of the Dynamic Pterodactyl extension as a companion to Paymenter’s built-in Pterodactyl integration. It explains how the extension hooks into Paymenter’s cart, invoice, and service lifecycle events to manage short-lived resource reservations, real-time availability checks against the Pterodactyl panel API, and Filament-based administration. The design emphasizes: -- Companion extension pattern (enhances, does not replace, the built-in Pterodactyl extension) -- Event-driven integration with Paymenter core -- Service-oriented separation between API controllers, business services, and data models -- Real-time API calls without caching -- Pessimistic database locking for reservation safety -- Strict reservation lifecycle states +This page is the canonical architecture guide for the branch that combines the +live `ResourceCalculationService` work with the Paymenter 1.5.6 reservation, +upgrade, and lifecycle remediation. The remaining Qoder pages are preserved so +their useful operational and historical detail is not lost. When an older page +mentions a retired controller, listener, or API shape, this page and the current +source take precedence. -**Section sources** -- [DynamicPterodactyl.php:25-40](file://DynamicPterodactyl.php#L25-L40) -- [DECISIONS.md:9-24](file://DECISIONS.md#L9-L24) -- [DECISIONS.md:28-44](file://DECISIONS.md#L28-L44) -- [DECISIONS.md:48-63](file://DECISIONS.md#L48-L63) +DynamicPterodactyl remains a companion to Paymenter's built-in Pterodactyl +extension. Paymenter owns products, invoices, services, and provisioning. This +extension adds live resource quotes, short-lived capacity commitments, node and +allocation selection, upgrade commitments, alerting, and operator tooling. -## Project Structure -The extension is organized by responsibility: -- Extension bootstrap and lifecycle: registers routes, policies, observers, event listeners, and scheduled jobs -- HTTP API layer: thin controllers that validate, authorize, and delegate to services -- Services: business logic for reservations, capacity calculations, node selection, alerts, and setup -- Models: Eloquent models for reservations and alert configuration -- Listeners: adapters from Paymenter core events to extension services -- Policies: authorization rules for reservations -- Admin UI: Filament resources and standalone Blade views -- Database migrations: schema for reservations, audit logs, alerts, and related tables +## Runtime Boundaries ```mermaid -graph TB -subgraph "Extension Bootstrap" -DP["DynamicPterodactyl::boot()"] -Routes["routes/api.php"] -Schedules["Scheduled Jobs"] -end -subgraph "API Layer" -AvailCtrl["AvailabilityController"] -ResCtrl["ReservationController"] -PricingCtrl["PricingController"] -AdminResCtrl["AdminReservationController"] -AdminCapCtrl["AdminCapacityController"] -end -subgraph "Business Services" -ResSvc["ReservationService"] -ResCalcSvc["ResourceCalculationService"] -NodeSelSvc["NodeSelectionService"] -AlertSvc["AlertService"] -end -subgraph "Data & Events" -Model["ResourceReservation"] -Policy["ResourceReservationPolicy"] -CartEvt["CartItemCreatedListener"] -InvoiceEvt["InvoicePaidListener"] -end -DP --> Routes -DP --> Schedules -Routes --> AvailCtrl -Routes --> ResCtrl -Routes --> PricingCtrl -Routes --> AdminResCtrl -Routes --> AdminCapCtrl -AvailCtrl --> ResCalcSvc -AvailCtrl --> NodeSelSvc -ResCtrl --> ResSvc -AdminResCtrl --> ResSvc -AdminCapCtrl --> ResCalcSvc -CartEvt --> ResSvc -InvoiceEvt --> ResSvc -InvoiceEvt --> ResCalcSvc -InvoiceEvt --> AlertSvc -ResSvc --> Model -ResSvc --> Policy -ResCalcSvc --> Model +flowchart LR + Browser["Checkout or upgrade UI"] --> Quote["ResourceQuoteController or UpgradeQuoteController"] + Quote --> QuoteService["ResourceQuoteService or UpgradeReservationService"] + QuoteService --> ProductConfig["ProductResourceConfigurationService"] + QuoteService --> Capacity["ResourceCalculationService"] + Capacity --> Inventory["PterodactylInventoryService"] + Inventory --> Panel["Pterodactyl application API"] + Cart["Paymenter cart events"] --> Reservation["ReservationService"] + Reservation --> Capacity + Provisioning["Paymenter service lifecycle"] --> Reservation + Upgrade["Paymenter service-upgrade lifecycle"] --> UpgradeReservation["UpgradeReservationService"] + UpgradeReservation --> Capacity + Capacity --> Policy["NodeCapacityPolicy"] ``` -**Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [routes/api.php:17-40](file://routes/api.php#L17-L40) -- [Http/Controllers/Api/AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Services/ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [Services/NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [Listeners/CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [Listeners/InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [Models/ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [Policies/ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) - -**Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [routes/api.php:17-40](file://routes/api.php#L17-L40) -- [AGENTS.md:11-25](file://AGENTS.md#L11-L25) - -## Core Components -- Extension bootstrap: loads routes, policy, observers, event listeners, and schedules -- Reservation service: creates, confirms, cancels, extends, and cleans up reservations with pessimistic locking and idempotency -- Resource calculation service: reads live Pterodactyl panel data to compute per-node and per-location availability; builds cluster snapshots -- Node selection service: selects best-fit nodes using weighted headroom scoring -- Listeners: bridge Paymenter core events to extension services -- Policies: enforce ownership and admin access on reservations -- Models: define reservation entity and scopes - -Key responsibilities are isolated so each component has a single reason to change: -- Controllers handle HTTP concerns only -- Services encapsulate domain logic -- Models represent persistence and simple queries -- Listeners adapt external events to internal actions - -**Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Services/ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [Services/NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [Listeners/CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [Listeners/InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [Models/ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [Policies/ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) - -## Architecture Overview -The extension follows an event-driven, service-oriented architecture layered over Paymenter core and the Pterodactyl panel API. - -System context diagram showing interactions between Paymenter core, Pterodactyl panel API, and extension components: - -```mermaid -graph TB -subgraph "Paymenter Core" -Cart["Cart Events"] -Invoice["Invoice Events"] -Service["Service Lifecycle"] -end -subgraph "Dynamic Pterodactyl Extension" -Boot["DynamicPterodactyl::boot()"] -Listeners["Event Listeners"] -Controllers["API Controllers"] -Services["Business Services"] -Models["Models & Policies"] -end -subgraph "Pterodactyl Panel API" -PteroNodes["/api/application/nodes"] -PteroLocs["/api/application/locations"] -PteroServers["/api/application/servers"] -end -Cart --> Listeners -Invoice --> Listeners -Service --> Listeners -Listeners --> Services -Controllers --> Services -Services --> Models -Services --> PteroNodes -Services --> PteroLocs -Services --> PteroServers -Boot --> Controllers -Boot --> Listeners -Boot --> Services -``` - -**Diagram sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [routes/api.php:17-40](file://routes/api.php#L17-L40) -- [Services/ResourceCalculationService.php:226-384](file://Services/ResourceCalculationService.php#L226-L384) -- [Listeners/CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [Listeners/InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) - -### Key Architectural Decisions -- Companion extension pattern: enhances the built-in Pterodactyl extension rather than replacing it, avoiding duplication of server provisioning logic and enabling graceful degradation if this extension fails. -- Real-time API calls: no caching of Pterodactyl responses to avoid staleness and overselling; batched API calls within a snapshot but never persisted cache. -- Database-backed reservations with pessimistic locking: prevents race conditions during checkout; includes deadlock retry and idempotency support. -- Strict reservation lifecycle: pending → confirmed | expired | cancelled; the released state was removed to simplify semantics and reduce ambiguity. -- Customer-facing endpoints expose aggregate capacity only; raw node-level data is admin-only. - -**Section sources** -- [DECISIONS.md:9-24](file://DECISIONS.md#L9-L24) -- [DECISIONS.md:28-44](file://DECISIONS.md#L28-L44) -- [DECISIONS.md:48-63](file://DECISIONS.md#L48-L63) -- [DECISIONS.md:233-239](file://DECISIONS.md#L233-L239) - -## Detailed Component Analysis - -### Extension Bootstrap and Event Wiring -The extension boot method: -- Registers the reservation policy -- Loads API routes -- Adds view namespace -- Registers event listeners for cart creation/deletion, invoice payment, and service creation -- Observes alert configuration changes -- Schedules cleanup of expired reservations and capacity alert checks - -```mermaid -sequenceDiagram -participant App as "Paymenter App" -participant Ext as "DynamicPterodactyl" -participant Routes as "routes/api.php" -participant Sched as "Scheduler" -participant Listeners as "Event Listeners" -App->>Ext : boot() -Ext->>Routes : require routes -Ext->>Listeners : register(cart/invoice/service) -Ext->>Sched : schedule(cleanup every minute) -Ext->>Sched : schedule(alerts every five minutes) -``` - -**Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [DynamicPterodactyl.php:132-145](file://DynamicPterodactyl.php#L132-L145) - -**Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) - -### Reservation Service: State Machine and Locking -Responsibilities: -- Create reservations with pessimistic DB locks and idempotency keys -- Confirm reservations after successful payment with final availability verification -- Cancel or extend reservations with authorization checks -- Clean up expired reservations via scheduled job -- Audit key transitions - -```mermaid -flowchart TD -Start(["create(token, location, resources)"]) --> Lock["Lock pending reservations by location"] -Lock --> Idem{"Idempotency key present?"} -Idem --> |Yes| CheckExisting["Check active reservation by key"] -CheckExisting --> Exists{"Existing active?"} -Exists --> |Yes| ReturnExisting["Return existing reservation"] -Exists --> |No| ExpireStale["Expire stale reservations by key"] -Idem --> |No| SelectNode["Select best node"] -SelectNode --> Found{"Node found?"} -Found --> |No| Error["Throw 'no node available'"] -Found --> |Yes| Insert["Insert reservation (pending)"] -Insert --> Present["Present reservation"] -Present --> End(["Done"]) -``` - -**Diagram sources** -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) - -```mermaid -stateDiagram-v2 -[*] --> Pending -Pending --> Confirmed : "confirm()" -Pending --> Expired : "cleanupExpired()" -Pending --> Cancelled : "cancel()" -Confirmed --> [*] -Expired --> [*] -Cancelled --> [*] -``` - -**Diagram sources** -- [Services/ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [Services/ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [Services/ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [DECISIONS.md:233-235](file://DECISIONS.md#L233-L235) - -**Section sources** -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Services/ReservationService.php:166-241](file://Services/ReservationService.php#L166-L241) -- [Services/ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [DECISIONS.md:48-63](file://DECISIONS.md#L48-L63) -- [DECISIONS.md:233-235](file://DECISIONS.md#L233-L235) - -### Resource Calculation Service: Real-Time Availability -Responsibilities: -- Fetch locations, nodes, and servers from Pterodactyl panel API -- Compute per-node and per-location availability including allocated and reserved resources -- Build cluster snapshots for admin dashboards -- Verify availability at payment time to prevent drift - -```mermaid -sequenceDiagram -participant Ctrl as "AvailabilityController" -participant ResCalc as "ResourceCalculationService" -participant Ptero as "Pterodactyl API" -Ctrl->>ResCalc : getLocationAvailability(locationId) -ResCalc->>Ptero : GET /locations/{id}?include=nodes,servers -ResCalc->>ResCalc : buildNodeAvailabilityFromServers(...) -ResCalc-->>Ctrl : {max_available, totals, allocated, nodes[]} -``` - -**Diagram sources** -- [Http/Controllers/Api/AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [Services/ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [Services/ResourceCalculationService.php:226-289](file://Services/ResourceCalculationService.php#L226-L289) - -**Section sources** -- [Services/ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [Services/ResourceCalculationService.php:226-384](file://Services/ResourceCalculationService.php#L226-L384) -- [Services/ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) - -### Node Selection Service: Best-Fit Scoring -Responsibilities: -- Filter candidates by requirements and maintenance mode -- Score nodes by remaining headroom with weights: memory 50%, disk 35%, CPU 15% -- Return the highest-scoring node or null if none fit - -```mermaid -flowchart TD -A["selectBestNode(location, requirements)"] --> B["Fetch location availability"] -B --> C{"For each node"} -C --> D{"Maintenance mode?"} -D --> |Yes| Skip["Skip node"] -D --> |No| E{"Has enough memory/cpu/disk?"} -E --> |No| Skip -E --> |Yes| F["Compute remaining headroom"] -F --> G["Score = mem*0.5 + disk*0.35 + cpu*0.15"] -G --> H{"More candidates?"} -H --> |Yes| C -H --> |No| I{"Any candidate?"} -I --> |No| J["Return null"] -I --> |Yes| K["Sort by score desc"] -K --> L["Return top node"] -``` - -**Diagram sources** -- [Services/NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) - -**Section sources** -- [Services/NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) - -### Event-Driven Checkout Flow -The extension integrates with Paymenter core through events: -- Cart item created: create a reservation and store token in checkout config -- Invoice paid: verify availability again, then confirm reservation; notify on shortfall or state drift -- Service created: log linkage for tracking - -```mermaid -sequenceDiagram -participant Core as "Paymenter Core" -participant CartEvt as "CartItemCreatedListener" -participant InvEvt as "InvoicePaidListener" -participant ResSvc as "ReservationService" -participant ResCalc as "ResourceCalculationService" -participant Alert as "AlertService" -Core-->>CartEvt : CartItemCreated -CartEvt->>ResSvc : create(productId, location, resources, cartItemId, userId) -ResSvc-->>CartEvt : reservation token -CartEvt->>Core : update checkout_config with token -Core-->>InvEvt : InvoicePaid -InvEvt->>ResSvc : getByToken(token) -InvEvt->>ResCalc : verifyAvailability(nodeId, requirements, token) -alt Available -InvEvt->>ResSvc : confirm(token, serviceId) -else Not available or state drift -InvEvt->>Alert : notifyShortfall(reason) -end -``` - -**Diagram sources** -- [Listeners/CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [Listeners/InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [Services/ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [Services/ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) - -**Section sources** -- [Listeners/CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [Listeners/InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) - -### API Layer and Authorization -- Customer endpoints: availability and pricing, throttled to protect Pterodactyl API budget; return aggregate capacity only -- Reservation endpoints: create/get/cancel/extend, throttled for checkout burst tolerance -- Admin endpoints: reservations list, cancel, capacity summary, node details; gated by admin middleware and policy - -Authorization: -- Policies allow admin bypass and enforce user ownership for customer actions -- Controllers rely on policies when passing actor context - -**Section sources** -- [routes/api.php:17-40](file://routes/api.php#L17-L40) -- [Http/Controllers/Api/AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [Policies/ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) - -### Data Models and Persistence -- ResourceReservation model defines fillable fields, casts, relationships, and scopes for pending/expired -- Migrations create reservation, audit, alert, and related tables -- Policies bind to the model for authorization - -**Section sources** -- [Models/ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) - -## Dependency Analysis -The extension exhibits clear separation of concerns: -- Controllers depend on services -- Services depend on models and external APIs -- Listeners depend on services -- Bootstrap wires routes, policies, listeners, and schedules - -```mermaid -graph LR -DP["DynamicPterodactyl::boot()"] --> R["routes/api.php"] -R --> AC["AvailabilityController"] -R --> RC["ReservationController"] -R --> PC["PricingController"] -R --> ARC["AdminReservationController"] -R --> ACC["AdminCapacityController"] -AC --> RCS["ResourceCalculationService"] -AC --> NSS["NodeSelectionService"] -RC --> RS["ReservationService"] -ARC --> RS -ACC --> RCS -L1["CartItemCreatedListener"] --> RS -L2["InvoicePaidListener"] --> RS -L2 --> RCS -L2 --> ALS["AlertService"] -RS --> RM["ResourceReservation"] -RS --> RP["ResourceReservationPolicy"] -RCS --> RM -``` - -**Diagram sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [routes/api.php:17-40](file://routes/api.php#L17-L40) -- [Http/Controllers/Api/AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Services/ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [Listeners/CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [Listeners/InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [Models/ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [Policies/ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) - -**Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [routes/api.php:17-40](file://routes/api.php#L17-L40) - -## Performance Considerations -- Real-time API calls: avoids cache staleness and overselling; uses connection timeouts and retries for resilience -- Batched API calls: cluster snapshot fetches locations and nodes efficiently while still being uncached -- Throttling: customer endpoints limited to 30 req/min; reservation endpoints to 10 req/min to protect Pterodactyl API budget -- Pessimistic locking: ensures correctness under concurrency; includes deadlock retry to improve throughput -- Scheduled jobs: run with overlap protection to avoid duplicate work - -[No sources needed since this section provides general guidance] - -## Troubleshooting Guide -Common issues and where to look: -- Reservation conflicts or deadlocks: check ReservationService transaction retries and idempotency handling -- Availability failures: inspect ResourceCalculationService API error surfaces and degraded snapshot behavior -- Shortfall notifications: review InvoicePaidListener shortfall path and AlertService delivery -- Admin visibility: ensure policies allow admin bypass and routes are correctly gated - -**Section sources** -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Services/ResourceCalculationService.php:410-498](file://Services/ResourceCalculationService.php#L410-L498) -- [Listeners/InvoicePaidListener.php:58-133](file://Listeners/InvoicePaidListener.php#L58-L133) -- [Policies/ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) - -## Conclusion -The Dynamic Pterodactyl extension integrates seamlessly with Paymenter’s built-in Pterodactyl integration through a companion extension pattern. Its event-driven architecture hooks into cart and invoice lifecycles to manage short-lived reservations backed by pessimistic database locking. The service-oriented design cleanly separates API concerns, business logic, and data models, while real-time API calls guarantee accurate availability. Strict reservation lifecycle states and admin-only exposure of node-level data further strengthen reliability and security. - -[No sources needed since this section summarizes without analyzing specific files] +The extension has four important boundaries: + +1. **Inventory boundary.** `PterodactylInventoryService` is the only component + that speaks the panel's application API. It reads every page, rejects missing + or inconsistent pagination, rejects duplicate resources, validates response + types, and sanitizes customer-visible failures. +2. **Capacity boundary.** `ResourceCalculationService` combines live node, + server, and allocation inventory with local reservations. CPU capacity comes + from the locally administered `NodeCapacityPolicy`; stock Pterodactyl does + not expose a `cpu_threads` node field. +3. **Commitment boundary.** `ReservationService` and + `UpgradeReservationService` use database locks, immutable snapshots, + idempotency, leases, and explicit state transitions. A quote never reserves + capacity by itself. +4. **Provisioning boundary.** Paid commitment and provisioning transitions are + owned by Paymenter's service and service-upgrade lifecycle. The reconciled + design does not use an extension `InvoicePaidListener` or + `ServiceCreatedListener`. + +## Live Inventory Contract + +The application API key needs read access to locations, nodes, servers, and +allocations. Inventory reads use the stock Pterodactyl 1.12.3+ shapes: + +- paginated `GET /api/application/locations`; +- paginated `GET /api/application/nodes?include=allocations`; +- paginated `GET /api/application/servers?include=allocations`; +- `GET /api/application/nodes/{id}/allocations` when a node-level allocation + refresh is required. + +Every paginated snapshot must keep the same total, page size, and last page for +its entire read. Required relationships and integral resource fields fail +closed. A partial or malformed upstream response is never interpreted as zero +usage or spare capacity. + +## Quote and Reservation Flow + +The customer-facing product endpoint accepts the full RAM, CPU, disk, and +allocation vector. `ProductResourceConfigurationService` resolves native +Paymenter config options; `ResourceQuoteService` then asks +`ResourceCalculationService` for a complete live bound and returns only +customer-safe aggregate data. + +Adding or updating a cart item invokes `CartItemCreatedListener`, which delegates +to `ReservationService::reserveForCartItem()`. Paymenter's surrounding database +transaction rolls back the cart mutation if capacity cannot be committed. +Deleting an item invokes `CartItemDeletedListener` and cancels its pending +commitment. Paid service and upgrade flows revalidate their signed snapshot +against current inventory before provisioning may continue. + +## HTTP Surface + +The reconciled API is intentionally small: + +| Method and path | Access | Purpose | +|---|---|---| +| `POST /api/dynamic-pterodactyl/products/{product}/resource-quote` | Guest-safe web session, throttled | Full-vector product quote without infrastructure identity | +| `POST /api/dynamic-pterodactyl/services/{service}/upgrade-quote` | Authenticated owner, throttled | Quote an existing-service upgrade | +| `GET /api/dynamic-pterodactyl/admin/reservations` | Admin | Inspect commitments | +| `POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel` | Admin | Cancel a commitment | +| `GET /api/dynamic-pterodactyl/admin/capacity` | Admin | Aggregate capacity snapshot | +| `GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes` | Admin | Node-level diagnostic inventory | + +There are no standalone public availability, pricing, create-reservation, +confirm-reservation, or extend-reservation endpoints. Pricing authority remains +in Paymenter core. + +## Operational Safety + +- The Pterodactyl application key is stored encrypted after the companion + Paymenter migration and is sent only in the `Authorization` header. +- Dynamic stock requires administrator-confirmed exclusive provisioning control + for every eligible node. Out-of-band creates, moves, resizes, or allocation + assignment can invalidate reservations. +- Scheduler heartbeats, bounded scans, failure records, and operator alerts make + cleanup and reconciliation failures visible. +- Customer responses never expose upstream bodies, API keys, node identities, + or internal exception details. +- The test harness accepts only an explicitly named test database or the private + `:temporary:` named-memory SQLite claim; production or shared databases are + rejected before Paymenter boots. + +## Source Guides + +For implementation-level detail, use these versioned repository guides: + +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md b/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md index 726cf6e..8c86fbd 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Companion Extension Pattern.md @@ -1,18 +1,21 @@ # Companion Extension Pattern +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [routes/api.php](file://routes/api.php) -- [Listeners/CartItemCreatedListener.php](file://Listeners/CartItemCreatedListener.php) -- [Listeners/InvoicePaidListener.php](file://Listeners/InvoicePaidListener.php) -- [Services/ReservationService.php](file://Services/ReservationService.php) -- [Services/ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [Services/AlertService.php](file://Services/AlertService.php) -- [Services/SliderConfigReaderService.php](file://Services/SliderConfigReaderService.php) -- [Models/ResourceReservation.php](file://Models/ResourceReservation.php) -- [AGENTS.md](file://AGENTS.md) -- [DECISIONS.md](file://DECISIONS.md) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php) +- [Listeners/InvoicePaidListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [Services/AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) +- [Services/SliderConfigReaderService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php) +- [Models/ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [AGENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/AGENTS.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md) ## Table of Contents @@ -32,9 +35,9 @@ This document explains the companion extension pattern used by Dynamic Pterodact The extension integrates through Paymenter’s Extension base class, registers routes and event listeners at boot, manages its own database migrations on install/uninstall, and coexists with core pricing and service management without interfering with provisioning logic. **Section sources** -- [DynamicPterodactyl.php:25-41](file://DynamicPterodactyl.php#L25-L41) -- [DECISIONS.md:9-25](file://DECISIONS.md#L9-L25) -- [AGENTS.md:7-10](file://AGENTS.md#L7-L10) +- [DynamicPterodactyl.php:25-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L25-L41) +- [DECISIONS.md:9-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L9-L25) +- [AGENTS.md:7-10](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/AGENTS.md#L7-L10) ## Project Structure At a high level, the extension is organized into: @@ -63,16 +66,16 @@ G --> M["Admin Recipients"] ``` **Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [routes/api.php:17-40](file://routes/api.php#L17-L40) -- [Services/ReservationService.php:16-35](file://Services/ReservationService.php#L16-L35) -- [Services/ResourceCalculationService.php:10-21](file://Services/ResourceCalculationService.php#L10-L21) -- [Services/AlertService.php:19-28](file://Services/AlertService.php#L19-L28) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [Services/ReservationService.php:16-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L35) +- [Services/ResourceCalculationService.php:10-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L10-L21) +- [Services/AlertService.php:19-28](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L19-L28) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [routes/api.php:17-40](file://routes/api.php#L17-L40) -- [AGENTS.md:11-26](file://AGENTS.md#L11-L26) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [AGENTS.md:11-26](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/AGENTS.md#L11-L26) ## Core Components - Extension bootstrap: installs migrations, registers policies, loads routes, adds view namespace, binds event listeners, and schedules cleanup/alert checks. @@ -83,13 +86,13 @@ G --> M["Admin Recipients"] - Event listeners: CartItemCreatedListener creates reservations when items are added; InvoicePaidListener performs final verification and confirmation; others handle deletion and service creation tracking. **Section sources** -- [DynamicPterodactyl.php:48-127](file://DynamicPterodactyl.php#L48-L127) -- [Services/ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) -- [Services/ResourceCalculationService.php:10-545](file://Services/ResourceCalculationService.php#L10-L545) -- [Services/AlertService.php:19-392](file://Services/AlertService.php#L19-L392) -- [Services/SliderConfigReaderService.php:7-68](file://Services/SliderConfigReaderService.php#L7-L68) -- [Listeners/CartItemCreatedListener.php:11-173](file://Listeners/CartItemCreatedListener.php#L11-L173) -- [Listeners/InvoicePaidListener.php:12-135](file://Listeners/InvoicePaidListener.php#L12-L135) +- [DynamicPterodactyl.php:48-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L48-L127) +- [Services/ReservationService.php:16-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L453) +- [Services/ResourceCalculationService.php:10-545](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L10-L545) +- [Services/AlertService.php:19-392](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L19-L392) +- [Services/SliderConfigReaderService.php:7-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L7-L68) +- [Listeners/CartItemCreatedListener.php:11-173](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L11-L173) +- [Listeners/InvoicePaidListener.php:12-135](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L12-L135) ## Architecture Overview The extension follows a companion pattern: @@ -122,14 +125,14 @@ Routes-->>Client : reservation response ``` **Diagram sources** -- [routes/api.php:24-30](file://routes/api.php#L24-L30) -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Services/ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L24-L30) +- [Services/ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [Services/ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) **Section sources** -- [DECISIONS.md:9-25](file://DECISIONS.md#L9-L25) -- [DECISIONS.md:28-45](file://DECISIONS.md#L28-L45) -- [DECISIONS.md:48-63](file://DECISIONS.md#L48-L63) +- [DECISIONS.md:9-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L9-L25) +- [DECISIONS.md:28-45](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L28-L45) +- [DECISIONS.md:48-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L48-L63) ## Detailed Component Analysis @@ -154,10 +157,10 @@ ScheduleAlerts --> End ``` **Diagram sources** -- [DynamicPterodactyl.php:77-127](file://DynamicPterodactyl.php#L77-L127) +- [DynamicPterodactyl.php:77-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L77-L127) **Section sources** -- [DynamicPterodactyl.php:48-127](file://DynamicPterodactyl.php#L48-L127) +- [DynamicPterodactyl.php:48-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L48-L127) ### Reservation Service: State Machine and Concurrency - Create: uses transaction with lockForUpdate on pending reservations for the target location, supports idempotency keys, selects best node, inserts reservation with TTL, and audits creation. @@ -184,10 +187,10 @@ Present --> Exit(["Exit"]) ``` **Diagram sources** -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [Services/ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) **Section sources** -- [Services/ReservationService.php:43-405](file://Services/ReservationService.php#L43-L405) +- [Services/ReservationService.php:43-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L405) ### Availability and Capacity: Real-Time Reads and Aggregation - Location availability fetches nodes in a location, calculates per-node availability including allocated servers and pending reservations, aggregates max available and totals. @@ -212,13 +215,13 @@ RSC-->>Controller : aggregated availability ``` **Diagram sources** -- [Services/ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [Services/ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) -- [Services/ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) +- [Services/ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [Services/ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) +- [Services/ResourceCalculationService.php:426-450](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L450) **Section sources** -- [Services/ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) -- [Services/ResourceCalculationService.php:197-214](file://Services/ResourceCalculationService.php#L197-L214) +- [Services/ResourceCalculationService.php:26-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L141) +- [Services/ResourceCalculationService.php:197-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L197-L214) ### Event Integration: Checkout Flow and Reconciliation - CartItemCreatedListener detects products with dynamic_slider options, extracts resource values and location, and creates a reservation storing token and selected node in checkout_config. @@ -244,12 +247,12 @@ IPay->>IPay : notifyShortfall on failure ``` **Diagram sources** -- [Listeners/CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [Listeners/InvoicePaidListener.php:14-135](file://Listeners/InvoicePaidListener.php#L14-L135) +- [Listeners/CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [Listeners/InvoicePaidListener.php:14-135](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L135) **Section sources** -- [Listeners/CartItemCreatedListener.php:13-173](file://Listeners/CartItemCreatedListener.php#L13-L173) -- [Listeners/InvoicePaidListener.php:14-135](file://Listeners/InvoicePaidListener.php#L14-L135) +- [Listeners/CartItemCreatedListener.php:13-173](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L173) +- [Listeners/InvoicePaidListener.php:14-135](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L135) ### Pricing Coexistence: Native Slider Metadata Only - SliderConfigReaderService reads dynamic_slider ConfigOption metadata (min, max, step, default, unit, display_unit, display_divisor, pricing model/rates) for frontend consumption. @@ -270,11 +273,11 @@ SliderConfigReaderService --> ConfigOption : "reads metadata" ``` **Diagram sources** -- [Services/SliderConfigReaderService.php:7-68](file://Services/SliderConfigReaderService.php#L7-L68) +- [Services/SliderConfigReaderService.php:7-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L7-L68) **Section sources** -- [Services/SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) -- [DECISIONS.md:67-84](file://DECISIONS.md#L67-L84) +- [Services/SliderConfigReaderService.php:14-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L53) +- [DECISIONS.md:67-84](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L67-L84) ### Admin Alerts and Observability - AlertService scans active alert configurations, computes utilization percentages, triggers warnings/criticals based on thresholds, and delivers notifications via email and webhook. @@ -300,12 +303,12 @@ NextConfig --> End(["Done"]) ``` **Diagram sources** -- [Services/AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [Services/AlertService.php:77-126](file://Services/AlertService.php#L77-L126) -- [Services/AlertService.php:128-248](file://Services/AlertService.php#L128-L248) +- [Services/AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [Services/AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) +- [Services/AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) **Section sources** -- [Services/AlertService.php:33-248](file://Services/AlertService.php#L33-L248) +- [Services/AlertService.php:33-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L248) ## Dependency Analysis The extension depends on: @@ -328,14 +331,14 @@ Policies --> RS ``` **Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [Services/ReservationService.php:16-35](file://Services/ReservationService.php#L16-L35) -- [Services/ResourceCalculationService.php:10-21](file://Services/ResourceCalculationService.php#L10-L21) -- [Services/AlertService.php:19-28](file://Services/AlertService.php#L19-L28) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [Services/ReservationService.php:16-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L35) +- [Services/ResourceCalculationService.php:10-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L10-L21) +- [Services/AlertService.php:19-28](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L19-L28) **Section sources** -- [AGENTS.md:43-58](file://AGENTS.md#L43-L58) -- [DECISIONS.md:28-45](file://DECISIONS.md#L28-L45) +- [AGENTS.md:43-58](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/AGENTS.md#L43-L58) +- [DECISIONS.md:28-45](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L28-L45) ## Performance Considerations - Real-time API calls are intentional to avoid staleness and overselling; rate limits and timeouts are handled with retries and degraded snapshots when necessary. @@ -353,10 +356,10 @@ Common issues and diagnostics: - Alert delivery failures: check AlertService sendNotifications and delivery logs; ensure email/webhook channels are configured and recipients exist. **Section sources** -- [Listeners/InvoicePaidListener.php:58-135](file://Listeners/InvoicePaidListener.php#L58-L135) -- [Services/ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [Services/ReservationService.php:125-141](file://Services/ReservationService.php#L125-L141) -- [Services/AlertService.php:128-248](file://Services/AlertService.php#L128-L248) +- [Listeners/InvoicePaidListener.php:58-135](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L58-L135) +- [Services/ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [Services/ReservationService.php:125-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L125-L141) +- [Services/AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) ## Conclusion Dynamic Pterodactyl implements a robust companion extension pattern that enhances Paymenter’s built-in Pterodactyl integration without replacing core functionality. It maintains separation of concerns by delegating pricing to core while owning reservations, availability, and alerts. The extension lifecycle is cleanly managed through installation, boot, and scheduled tasks, and it integrates deeply with Paymenter’s event system to ensure reliable checkout flows. Real-time API access, pessimistic locking, and thorough auditing provide correctness and observability, while admin tools and Filament 4 interfaces offer operational control. diff --git a/.qoder/repowiki/en/content/Architecture Overview/Data Consistency Model.md b/.qoder/repowiki/en/content/Architecture Overview/Data Consistency Model.md index a08a07b..3d1e47c 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Data Consistency Model.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Data Consistency Model.md @@ -1,17 +1,20 @@ # Data Consistency Model +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [ReservationService.php](file://Services/ReservationService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) -- [2026_04_22_000001_drop_released_from_reservation_status.php](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) -- [ReservationController.php](file://Http/Controllers/Api/ReservationController.php) -- [api.php](file://routes/api.php) -- [ResourceReservationPolicy.php](file://Policies/ResourceReservationPolicy.php) -- [ReservationApiTest.php](file://tests/Feature/ReservationApiTest.php) -- [ReservationServiceTest.php](file://tests/Unit/ReservationServiceTest.php) -- [DECISIONS.md](file://DECISIONS.md) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) +- [2026_04_22_000001_drop_released_from_reservation_status.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) +- [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) +- [api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [ResourceReservationPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php) +- [ReservationApiTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php) +- [ReservationServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md) ## Table of Contents @@ -49,14 +52,14 @@ Service --> Audit["Audit Log
AuditsExtensionActions"] ``` **Diagram sources** -- [api.php:17-40](file://routes/api.php#L17-L40) -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ResourceReservationPolicy.php:14-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L68) **Section sources** -- [api.php:17-40](file://routes/api.php#L17-L40) -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) ## Core Components - ReservationService: Implements pessimistic locking, idempotency, TTL management, confirm/cancel/extend, and cleanup. @@ -73,11 +76,11 @@ Key responsibilities: - Clean up expired reservations automatically **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-25](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L25) -- [ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L25) +- [ResourceReservationPolicy.php:14-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L68) ## Architecture Overview The reservation flow uses a transactional boundary around lock acquisition, node selection, and reservation insertion. Confirm, cancel, and extend operate as atomic updates guarded by state checks. A scheduled cleanup marks pending reservations past their TTL as expired. @@ -108,12 +111,12 @@ end ``` **Diagram sources** -- [ReservationController.php:24-60](file://Http/Controllers/Api/ReservationController.php#L24-L60) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [ReservationController.php:24-60](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L60) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) **Section sources** -- [ReservationController.php:24-60](file://Http/Controllers/Api/ReservationController.php#L24-L60) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [ReservationController.php:24-60](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L60) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) ## Detailed Component Analysis @@ -137,10 +140,10 @@ Commit --> Return["Return reservation"] ``` **Diagram sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) ### Idempotent Creation and Duplicate Handling - If an idempotency key is provided, stale pending reservations tied to that key are expired before checking for an existing active reservation. @@ -166,16 +169,16 @@ end ``` **Diagram sources** -- [ReservationService.php:60-73](file://Services/ReservationService.php#L60-L73) -- [ReservationService.php:143-157](file://Services/ReservationService.php#L143-L157) -- [ReservationService.php:431-442](file://Services/ReservationService.php#L431-L442) -- [ReservationService.php:444-452](file://Services/ReservationService.php#L444-L452) +- [ReservationService.php:60-73](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L60-L73) +- [ReservationService.php:143-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L143-L157) +- [ReservationService.php:431-442](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L431-L442) +- [ReservationService.php:444-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L444-L452) **Section sources** -- [ReservationService.php:60-73](file://Services/ReservationService.php#L60-L73) -- [ReservationService.php:143-157](file://Services/ReservationService.php#L143-L157) -- [ReservationService.php:431-442](file://Services/ReservationService.php#L431-L442) -- [ReservationService.php:444-452](file://Services/ReservationService.php#L444-L452) +- [ReservationService.php:60-73](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L60-L73) +- [ReservationService.php:143-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L143-L157) +- [ReservationService.php:431-442](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L431-L442) +- [ReservationService.php:444-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L444-L452) ### Strict Reservation Lifecycle States - The lifecycle is strictly: pending → confirmed | expired | cancelled. @@ -193,18 +196,18 @@ cancelled --> [*] ``` **Diagram sources** -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-25](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L25) -- [DECISIONS.md:233-235](file://DECISIONS.md#L233-L235) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L25) +- [DECISIONS.md:233-235](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L233-L235) **Section sources** -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-25](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L25) -- [DECISIONS.md:233-235](file://DECISIONS.md#L233-L235) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L25) +- [DECISIONS.md:233-235](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L233-L235) ### TTL-Based Reservations and Automatic Cleanup - Each reservation has an `expires_at` timestamp set to now + TTL minutes (default 15). @@ -220,11 +223,11 @@ Audit --> End(["Done"]) ``` **Diagram sources** -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) **Section sources** -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [ReservationService.php:250-281](file://Services/ReservationService.php#L250-L281) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [ReservationService.php:250-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L250-L281) ### Transaction Boundaries and Rollback Scenarios - Create: Entire operation (lock, node selection, insert) is inside a transaction with retries. Any exception causes rollback. @@ -243,10 +246,10 @@ Recovery: - Audit failures do not break core operations; they are logged safely. **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ReservationService.php:250-281](file://Services/ReservationService.php#L250-L281) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ReservationService.php:250-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L250-L281) ### Authorization and Ownership Enforcement - Policies enforce that users can only view, cancel, or extend their own reservations. @@ -273,26 +276,26 @@ ReservationController --> ResourceReservationPolicy : "authorize()" ``` **Diagram sources** -- [ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) -- [ReservationController.php:62-136](file://Http/Controllers/Api/ReservationController.php#L62-L136) +- [ResourceReservationPolicy.php:14-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L68) +- [ReservationController.php:62-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L62-L136) **Section sources** -- [ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) -- [ReservationController.php:62-136](file://Http/Controllers/Api/ReservationController.php#L62-L136) +- [ResourceReservationPolicy.php:14-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L68) +- [ReservationController.php:62-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L62-L136) ### API Endpoints and Throttling - Customer endpoints: create, get, cancel, extend under a throttle of 10 requests per minute to tolerate checkout retries without enabling abuse. - Admin endpoints: list reservations, cancel reservations, capacity summary, and node availability under separate middleware and throttling. **Section sources** -- [api.php:17-40](file://routes/api.php#L17-L40) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ### Data Model and Indexes - The reservations table includes fields for token, idempotency key, links to cart/service/user, node/location, reserved resources, pricing snapshot, status, notes, and timestamps. - Indexes optimize queries for cleanup, location-based locking, and filtering by status and time. **Section sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) ## Dependency Analysis - Controllers depend on services for business logic and on policies for authorization. @@ -310,14 +313,14 @@ Model["ResourceReservation"] --> DB ``` **Diagram sources** -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) **Section sources** -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ## Performance Considerations - Exclusive locks prevent overselling but serialize concurrent reservation attempts per location. This is necessary for correctness. @@ -339,10 +342,10 @@ Operational checks: - Monitor throttle responses (429) on reservation endpoints to detect burst patterns. **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [ReservationApiTest.php:37-78](file://tests/Feature/ReservationApiTest.php#L37-L78) -- [ReservationServiceTest.php:259-285](file://tests/Unit/ReservationServiceTest.php#L259-L285) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [ReservationApiTest.php:37-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L37-L78) +- [ReservationServiceTest.php:259-285](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L259-L285) ## Conclusion The reservation system enforces data consistency through pessimistic locking, strict lifecycle transitions, and robust idempotency. The removal of the 'released' state clarifies the observable lifecycle to pending → confirmed | expired | cancelled. TTL-based reservations with automatic cleanup ensure resources are not held indefinitely. Transactions and retries protect against deadlocks and transient failures, while policies and audits maintain security and observability. This design balances correctness, performance, and operational clarity for accurate resource allocation under concurrent load. diff --git a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Cart Events and Listeners.md b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Cart Events and Listeners.md index 3f3e1c1..77d8b1c 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Cart Events and Listeners.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Cart Events and Listeners.md @@ -1,17 +1,20 @@ # Cart Events and Listeners +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [CartItemCreatedListener.php](file://Listeners/CartItemCreatedListener.php) -- [CartItemDeletedListener.php](file://Listeners/CartItemDeletedListener.php) -- [InvoicePaidListener.php](file://Listeners/InvoicePaidListener.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [NodeSelectionService.php](file://Services/NodeSelectionService.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php) +- [CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php) +- [InvoicePaidListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [NodeSelectionService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) ## Table of Contents @@ -54,16 +57,16 @@ E --> K["ReservationService::confirm()"] ``` **Diagram sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-134](file://Listeners/InvoicePaidListener.php#L14-L134) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-134](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L134) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) **Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) ## Core Components - CartItemCreatedListener: Detects dynamic slider products, extracts resource requirements and location, creates a reservation via ReservationService, and stores the reservation token and selected node in the cart item’s checkout configuration. @@ -75,13 +78,13 @@ E --> K["ReservationService::confirm()"] - ResourceReservation model: Defines fillable fields, casts, and scopes for pending/expired reservations. **Section sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-134](file://Listeners/InvoicePaidListener.php#L14-L134) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-134](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L134) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ## Architecture Overview The cart event flow ensures resources are reserved for a limited window during checkout: @@ -122,11 +125,11 @@ Note over ResSvc,DB : Transaction commits; lock released ``` **Diagram sources** -- [DynamicPterodactyl.php:134-138](file://DynamicPterodactyl.php#L134-L138) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [DynamicPterodactyl.php:134-138](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L134-L138) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) ## Detailed Component Analysis @@ -161,10 +164,10 @@ LogInfo --> End(["Exit"]) ``` **Diagram sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) **Section sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) ### CartItemDeletedListener Responsibilities: @@ -192,10 +195,10 @@ CancelRes --> LogCancel["Log cancellation success"] --> EndD ``` **Diagram sources** -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) **Section sources** -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) ### InvoicePaidListener Responsibilities: @@ -234,10 +237,10 @@ end ``` **Diagram sources** -- [InvoicePaidListener.php:14-134](file://Listeners/InvoicePaidListener.php#L14-L134) +- [InvoicePaidListener.php:14-134](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L134) **Section sources** -- [InvoicePaidListener.php:14-134](file://Listeners/InvoicePaidListener.php#L14-L134) +- [InvoicePaidListener.php:14-134](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L134) ### ReservationService Core responsibilities: @@ -283,14 +286,14 @@ NodeSelectionService --> ResourceCalculationService : "uses" ``` **Diagram sources** -- [ReservationService.php:16-141](file://Services/ReservationService.php#L16-L141) -- [NodeSelectionService.php:5-76](file://Services/NodeSelectionService.php#L5-L76) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [ReservationService.php:16-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L141) +- [NodeSelectionService.php:5-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L5-L76) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-241](file://Services/ReservationService.php#L166-L241) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L241) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) ### NodeSelectionService Algorithm: @@ -303,7 +306,7 @@ Output: - Returns the best node or null if none qualify. **Section sources** -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) ### ResourceCalculationService Capabilities: @@ -318,10 +321,10 @@ API integration: - Produces degraded snapshots when API is unavailable. **Section sources** -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceCalculationService.php:198-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L198-L214) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) ### Data Model and Schema - ResourceReservation model defines fillable fields, casts, and relationships to User and Service. @@ -330,9 +333,9 @@ API integration: - Idempotency migration adds idempotency_key and active_idempotency_key with unique constraint to prevent duplicate active reservations. **Section sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:11-20](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L11-L20) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:11-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L11-L20) ## Dependency Analysis The cart event handling depends on several components: @@ -358,16 +361,16 @@ RSvc --> DB["ptero_resource_reservations"] ``` **Diagram sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-134](file://Listeners/InvoicePaidListener.php#L14-L134) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-134](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L134) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) **Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) ## Performance Considerations - Real-time API calls: Availability checks call Pterodactyl API directly; this avoids stale cache but introduces latency. Batch fetching and pagination mitigate overhead. @@ -405,10 +408,10 @@ Common issues and strategies: - Action: Review logs for state drift; alerts may be triggered; re-check availability and consider manual intervention. **Section sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-134](file://Listeners/InvoicePaidListener.php#L14-L134) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-134](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L134) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) ## Conclusion The Dynamic Pterodactyl extension implements a robust cart event-driven reservation system that secures compute resources during checkout with a 15-minute TTL. It combines real-time availability checks, best-fit node selection, pessimistic locking, and idempotency to maintain data consistency and prevent overselling. Graceful degradation ensures the customer experience remains uninterrupted even when external systems fail. Scheduled cleanup keeps the system accurate by transitioning expired reservations. Together, these mechanisms provide reliable resource allocation aligned with payment flows. diff --git a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Complete Checkout Flow Integration.md b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Complete Checkout Flow Integration.md index a622764..5e50556 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Complete Checkout Flow Integration.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Complete Checkout Flow Integration.md @@ -1,21 +1,24 @@ # Complete Checkout Flow Integration +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [CartItemCreatedListener.php](file://Listeners/CartItemCreatedListener.php) -- [CartItemDeletedListener.php](file://Listeners/CartItemDeletedListener.php) -- [InvoicePaidListener.php](file://Listeners/InvoicePaidListener.php) -- [ServiceCreatedListener.php](file://Listeners/ServiceCreatedListener.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [NodeSelectionService.php](file://Services/NodeSelectionService.php) -- [AlertService.php](file://Services/AlertService.php) -- [AlertDeliveryFailed.php](file://Events/AlertDeliveryFailed.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [api.php](file://routes/api.php) -- [ReservationController.php](file://Http/Controllers/Api/ReservationController.php) -- [AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php) +- [CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php) +- [InvoicePaidListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php) +- [ServiceCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [NodeSelectionService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php) +- [AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) +- [AlertDeliveryFailed.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) +- [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) ## Table of Contents @@ -91,20 +94,20 @@ NSS --> RCS ``` **Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [api.php:17-40](file://routes/api.php#L17-L40) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ResourceCalculationService.php:200-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L200-L214) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [api.php:17-40](file://routes/api.php#L17-L40) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ## Core Components - Event registration and scheduling: Extension boot wires up event listeners and schedules cleanup and alert checks. @@ -118,13 +121,13 @@ NSS --> RCS - Controllers and routes: Expose availability, pricing, and reservation management endpoints. **Section sources** -- [DynamicPterodactyl.php:106-145](file://DynamicPterodactyl.php#L106-L145) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [api.php:17-40](file://routes/api.php#L17-L40) +- [DynamicPterodactyl.php:106-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L106-L145) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ResourceCalculationService.php:200-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L200-L214) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ## Architecture Overview The checkout flow is event-driven and stateful: @@ -191,15 +194,15 @@ L4->>DB : Log linkage (reservation token present) ``` **Diagram sources** -- [AvailabilityController.php:22-51](file://Http/Controllers/Api/AvailabilityController.php#L22-L51) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) +- [AvailabilityController.php:22-51](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L51) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) ## Detailed Component Analysis @@ -216,9 +219,9 @@ Key responsibilities: - Provide admin-only endpoints gated by middleware **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [DynamicPterodactyl.php:132-145](file://DynamicPterodactyl.php#L132-L145) -- [api.php:17-40](file://routes/api.php#L17-L40) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [DynamicPterodactyl.php:132-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L132-L145) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ### Cart Item Created → Reservation Creation Trigger: Paymenter emits CartItem\Created when a user adds a product with dynamic_slider options. @@ -236,9 +239,9 @@ Edge cases: - No suitable node → exception logged; user can still proceed without guaranteed resources **Section sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) ### Cart Item Deleted → Reservation Cancellation Trigger: Paymenter emits CartItem\Deleted when a cart item is removed. @@ -252,7 +255,7 @@ Edge cases: - If service already references the token, cancellation is skipped to avoid race conditions with payment confirmation **Section sources** -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) ### Invoice Paid → Final Verification and Confirmation Trigger: Paymenter emits Invoice\Paid after successful payment. @@ -270,9 +273,9 @@ Edge cases: - Confirm returns false due to state drift → shortfall alert with drift reason **Section sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ResourceCalculationService.php:200-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L200-L214) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) ### Service Created → Tracking Trigger: Paymenter emits Service\Created after service provisioning begins. @@ -285,7 +288,7 @@ Purpose: - Audit trail and correlation between services and reservations **Section sources** -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) ### Reservation Lifecycle and State Transitions States: @@ -310,17 +313,17 @@ Expired --> [*] ``` **Diagram sources** -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [ResourceReservation.php:51-64](file://Models/ResourceReservation.php#L51-L64) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [ResourceReservation.php:51-64](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L51-L64) **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [ResourceReservation.php:51-64](file://Models/ResourceReservation.php#L51-L64) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [ResourceReservation.php:51-64](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L51-L64) ### Node Selection Algorithm Algorithm: @@ -347,10 +350,10 @@ ReturnBest --> |No| None["Return null"] ``` **Diagram sources** -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) **Section sources** -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) ### Availability and Pricing APIs Endpoints: @@ -368,9 +371,9 @@ Security: - Admin routes require authentication and admin role middleware **Section sources** -- [api.php:17-40](file://routes/api.php#L17-L40) -- [AvailabilityController.php:22-71](file://Http/Controllers/Api/AvailabilityController.php#L22-L71) -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [AvailabilityController.php:22-71](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L71) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) ## Dependency Analysis The checkout flow depends on several internal and external components: @@ -401,22 +404,22 @@ Potential circular dependencies: - None observed; dependencies are directional from listeners to services to external API **Diagram sources** -- [DynamicPterodactyl.php:132-145](file://DynamicPterodactyl.php#L132-L145) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) +- [DynamicPterodactyl.php:132-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L132-L145) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ResourceCalculationService.php:200-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L200-L214) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) **Section sources** -- [DynamicPterodactyl.php:132-145](file://DynamicPterodactyl.php#L132-L145) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) +- [DynamicPterodactyl.php:132-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L132-L145) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ResourceCalculationService.php:200-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L200-L214) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) ## Performance Considerations - Real-time availability: Always fetches from Pterodactyl API; no caching ensures accuracy but increases latency and API usage @@ -460,12 +463,12 @@ Debugging techniques: - Validate Pterodactyl API connectivity and rate limits **Section sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) -- [AlertDeliveryFailed.php:9-16](file://Events/AlertDeliveryFailed.php#L9-L16) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) +- [AlertDeliveryFailed.php:9-16](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L16) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) ## Conclusion The checkout flow integrates tightly with Paymenter core events to provide dynamic resource reservations and real-time availability checks. The event-driven design ensures clear separation of concerns, robust concurrency handling, and comprehensive observability through logging and alerts. Edge cases like cart abandonment, payment failures, and provisioning errors are handled gracefully with fallbacks and notifications. Scheduled maintenance keeps the system consistent and reliable over time. \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event Registration and Configuration.md b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event Registration and Configuration.md index 46c17b6..559cddd 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event Registration and Configuration.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event Registration and Configuration.md @@ -1,17 +1,20 @@ # Event Registration and Configuration +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [CartItemCreatedListener.php](file://Listeners/CartItemCreatedListener.php) -- [CartItemDeletedListener.php](file://Listeners/CartItemDeletedListener.php) -- [InvoicePaidListener.php](file://Listeners/InvoicePaidListener.php) -- [ServiceCreatedListener.php](file://Listeners/ServiceCreatedListener.php) -- [AlertDeliveryFailed.php](file://Events/AlertDeliveryFailed.php) -- [AlertService.php](file://Services/AlertService.php) -- [AlertDeliveryLog.php](file://Models/AlertDeliveryLog.php) -- [CartItemDeletedListenerTest.php](file://tests/Unit/CartItemDeletedListenerTest.php) -- [InvoicePaidListenerTest.php](file://tests/Unit/InvoicePaidListenerTest.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php) +- [CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php) +- [InvoicePaidListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php) +- [ServiceCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php) +- [AlertDeliveryFailed.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php) +- [AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) +- [AlertDeliveryLog.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php) +- [CartItemDeletedListenerTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/CartItemDeletedListenerTest.php) +- [InvoicePaidListenerTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/InvoicePaidListenerTest.php) ## Table of Contents @@ -84,16 +87,16 @@ S3 --> D1 ``` **Diagram sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) -- [AlertService.php:128-247](file://Services/AlertService.php#L128-L247) -- [AlertDeliveryFailed.php:9-15](file://Events/AlertDeliveryFailed.php#L9-L15) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) +- [AlertService.php:128-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L247) +- [AlertDeliveryFailed.php:9-15](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L15) **Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) ## Core Components - Event registration occurs in the extension’s boot method via Laravel’s Event facade. Four Paymenter core events are mapped to dedicated listeners: @@ -109,9 +112,9 @@ Key responsibilities: - Domain events decouple failure reporting from primary flows **Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [AlertDeliveryFailed.php:9-15](file://Events/AlertDeliveryFailed.php#L9-L15) -- [AlertService.php:128-247](file://Services/AlertService.php#L128-L247) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) +- [AlertDeliveryFailed.php:9-15](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L15) +- [AlertService.php:128-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L247) ## Architecture Overview The extension integrates with Paymenter’s event system by registering listeners during boot. Each listener handles one stage of the checkout lifecycle and coordinates with services to perform side effects such as reserving resources or sending alerts. @@ -151,11 +154,11 @@ LService-->>Paymenter : Log linkage only ``` **Diagram sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) ## Detailed Component Analysis @@ -174,7 +177,7 @@ Best practices demonstrated: - Exceptions in listeners are caught and logged so they do not block core flows **Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) ### CartItemCreatedListener Responsibilities: @@ -188,8 +191,8 @@ Error handling: - Gracefully continues even if reservation creation fails, ensuring checkout can proceed without guaranteed resources **Section sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemCreatedListener.php:93-172](file://Listeners/CartItemCreatedListener.php#L93-L172) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemCreatedListener.php:93-172](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L93-L172) ### CartItemDeletedListener Responsibilities: @@ -202,10 +205,10 @@ Race condition safeguard: - If a service exists with the same reservation token, the deletion is treated as part of a successful checkout and cancellation is skipped **Section sources** -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [CartItemDeletedListenerTest.php:33-68](file://tests/Unit/CartItemDeletedListenerTest.php#L33-L68) -- [CartItemDeletedListenerTest.php:70-95](file://tests/Unit/CartItemDeletedListenerTest.php#L70-L95) -- [CartItemDeletedListenerTest.php:97-125](file://tests/Unit/CartItemDeletedListenerTest.php#L97-L125) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [CartItemDeletedListenerTest.php:33-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/CartItemDeletedListenerTest.php#L33-L68) +- [CartItemDeletedListenerTest.php:70-95](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/CartItemDeletedListenerTest.php#L70-L95) +- [CartItemDeletedListenerTest.php:97-125](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/CartItemDeletedListenerTest.php#L97-L125) ### InvoicePaidListener Responsibilities: @@ -220,9 +223,9 @@ Critical checks: - State drift detection triggers alerts when the reservation cannot be confirmed due to status changes between checks **Section sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [InvoicePaidListenerTest.php:25-61](file://tests/Unit/InvoicePaidListenerTest.php#L25-L61) -- [InvoicePaidListenerTest.php:63-102](file://tests/Unit/InvoicePaidListenerTest.php#L63-L102) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [InvoicePaidListenerTest.php:25-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/InvoicePaidListenerTest.php#L25-L61) +- [InvoicePaidListenerTest.php:63-102](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/InvoicePaidListenerTest.php#L63-L102) ### ServiceCreatedListener Responsibilities: @@ -230,7 +233,7 @@ Responsibilities: - Does not alter reservation state; confirmation is handled by the invoice paid flow **Section sources** -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) ### Custom Event: AlertDeliveryFailed Purpose: @@ -246,8 +249,8 @@ Design notes: - Accepts a readonly AlertDeliveryLog to preserve immutability of the payload **Section sources** -- [AlertDeliveryFailed.php:9-15](file://Events/AlertDeliveryFailed.php#L9-L15) -- [AlertService.php:218-236](file://Services/AlertService.php#L218-L236) +- [AlertDeliveryFailed.php:9-15](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L15) +- [AlertService.php:218-236](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L218-L236) ### AlertService Integration Responsibilities: @@ -262,11 +265,11 @@ Failure handling: - Reports throwables through the application exception handler when available **Section sources** -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:128-247](file://Services/AlertService.php#L128-L247) -- [AlertService.php:250-299](file://Services/AlertService.php#L250-L299) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertService.php:128-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L247) +- [AlertService.php:250-299](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L250-L299) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) ## Dependency Analysis The extension depends on Paymenter core events and provides listeners that coordinate with internal services. Dependencies are intentionally loose: @@ -310,17 +313,17 @@ AlertService --> AlertDeliveryLog : "writes" ``` **Diagram sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) -- [AlertService.php:128-247](file://Services/AlertService.php#L128-L247) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) +- [AlertService.php:128-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L247) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) **Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [AlertService.php:128-247](file://Services/AlertService.php#L128-L247) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) +- [AlertService.php:128-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L247) ## Performance Considerations - Event listeners avoid blocking core flows by catching exceptions and logging errors instead of failing loudly @@ -350,10 +353,10 @@ Operational tips: - Monitor logs for error entries related to reservation processing and alert delivery **Section sources** -- [CartItemDeletedListener.php:24-40](file://Listeners/CartItemDeletedListener.php#L24-L40) -- [InvoicePaidListener.php:58-90](file://Listeners/InvoicePaidListener.php#L58-L90) -- [InvoicePaidListener.php:103-125](file://Listeners/InvoicePaidListener.php#L103-L125) -- [AlertService.php:218-247](file://Services/AlertService.php#L218-L247) +- [CartItemDeletedListener.php:24-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L24-L40) +- [InvoicePaidListener.php:58-90](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L58-L90) +- [InvoicePaidListener.php:103-125](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L103-L125) +- [AlertService.php:218-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L218-L247) ## Conclusion The Dynamic Pterodactyl extension integrates cleanly with Paymenter’s event system by registering focused listeners during boot. It extends existing functionality without conflicts by: @@ -376,8 +379,8 @@ This design supports scalable, maintainable event-driven architecture for extens - Custom AlertDeliveryFailed → dispatched by AlertService on delivery failure **Section sources** -- [DynamicPterodactyl.php:134-145](file://DynamicPterodactyl.php#L134-L145) -- [AlertService.php:218-236](file://Services/AlertService.php#L218-L236) +- [DynamicPterodactyl.php:134-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L134-L145) +- [AlertService.php:218-236](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L218-L236) ### Best Practices for Event-Driven Extensions - Register listeners centrally in boot to keep wiring explicit diff --git a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event-Driven Architecture.md b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event-Driven Architecture.md index 378c14b..01cd191 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event-Driven Architecture.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Event-Driven Architecture.md @@ -1,18 +1,21 @@ # Event-Driven Architecture +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [CartItemCreatedListener.php](file://Listeners/CartItemCreatedListener.php) -- [CartItemDeletedListener.php](file://Listeners/CartItemDeletedListener.php) -- [InvoicePaidListener.php](file://Listeners/InvoicePaidListener.php) -- [ServiceCreatedListener.php](file://Listeners/ServiceCreatedListener.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [AuditLogService.php](file://Services/AuditLogService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) -- [2025_01_01_000003_create_ptero_audit_logs_table.php](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php) +- [CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php) +- [InvoicePaidListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php) +- [ServiceCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [AuditLogService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) +- [2025_01_01_000003_create_ptero_audit_logs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) ## Table of Contents @@ -51,16 +54,16 @@ J --> M["Pterodactyl API"] ``` **Diagram sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ResourceCalculationService.php:198-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L198-L214) **Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) ## Core Components - Event registration: The extension boots and registers listeners for CartItemCreated, CartItemDeleted, InvoicePaid, and ServiceCreated. @@ -78,14 +81,14 @@ Key responsibilities: - ServiceCreatedListener: Log linkage between service and reservation for audit purposes. **Section sources** -- [DynamicPterodactyl.php:106-145](file://DynamicPterodactyl.php#L106-L145) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [DynamicPterodactyl.php:106-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L106-L145) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ResourceCalculationService.php:198-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L198-L214) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ## Architecture Overview The checkout flow is event-driven and asynchronous at the boundaries (events fire around core actions). The extension ensures consistency by: @@ -121,9 +124,9 @@ Listener-->>Paymenter : update cart checkout_config with token ``` **Diagram sources** -- [DynamicPterodactyl.php:132-145](file://DynamicPterodactyl.php#L132-L145) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [DynamicPterodactyl.php:132-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L132-L145) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) ## Detailed Component Analysis @@ -141,10 +144,10 @@ Schedules --> End(["Ready"]) ``` **Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) ### CartItemCreatedListener: Reservation Creation Responsibilities: @@ -169,10 +172,10 @@ F --> G["Log success"] ``` **Diagram sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) **Section sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) ### CartItemDeletedListener: Reservation Cancellation Responsibilities: @@ -191,10 +194,10 @@ F --> G["Log cancellation"] ``` **Diagram sources** -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) **Section sources** -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) ### InvoicePaidListener: Reservation Confirmation and Availability Verification Responsibilities: @@ -240,12 +243,12 @@ end ``` **Diagram sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ResourceCalculationService.php:198-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L198-L214) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) **Section sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) ### ServiceCreatedListener: Audit Trail Entry Responsibilities: @@ -263,10 +266,10 @@ C -- Yes --> D["Log service-reservation linkage"] ``` **Diagram sources** -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) **Section sources** -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) ### ReservationService: Concurrency, Idempotency, and Lifecycle Key behaviors: @@ -310,20 +313,20 @@ ReservationService --> ResourceReservation : "persists" ``` **Diagram sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ReservationService.php:250-281](file://Services/ReservationService.php#L250-L281) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ReservationService.php:250-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L250-L281) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ReservationService.php:250-281](file://Services/ReservationService.php#L250-L281) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ReservationService.php:250-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L250-L281) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ### ResourceCalculationService: Real-Time Availability Responsibilities: @@ -344,14 +347,14 @@ G -- No --> I["Return false"] ``` **Diagram sources** -- [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) -- [ResourceCalculationService.php:500-522](file://Services/ResourceCalculationService.php#L500-L522) +- [ResourceCalculationService.php:198-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L198-L214) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) +- [ResourceCalculationService.php:500-522](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L500-L522) **Section sources** -- [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) -- [ResourceCalculationService.php:500-522](file://Services/ResourceCalculationService.php#L500-L522) +- [ResourceCalculationService.php:198-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L198-L214) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) +- [ResourceCalculationService.php:500-522](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L500-L522) ### Audit Logging All critical reservation actions are audited via ReservationService’s safeAudit helper, which uses AuditLogService to persist changes with user context and request metadata. @@ -364,15 +367,15 @@ C --> D["ptero_audit_logs row"] ``` **Diagram sources** -- [ReservationService.php:102-113](file://Services/ReservationService.php#L102-L113) -- [ReservationService.php:191-196](file://Services/ReservationService.php#L191-L196) -- [ReservationService.php:233-238](file://Services/ReservationService.php#L233-L238) -- [ReservationService.php:272-278](file://Services/ReservationService.php#L272-L278) -- [ReservationService.php:397-402](file://Services/ReservationService.php#L397-L402) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) +- [ReservationService.php:102-113](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L102-L113) +- [ReservationService.php:191-196](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L191-L196) +- [ReservationService.php:233-238](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L233-L238) +- [ReservationService.php:272-278](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L272-L278) +- [ReservationService.php:397-402](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L397-L402) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) **Section sources** -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) ## Dependency Analysis The extension depends on Paymenter core events and services, and integrates with Pterodactyl for real-time availability. @@ -395,12 +398,12 @@ RCS --> Ptero["Pterodactyl API"] ``` **Diagram sources** -- [DynamicPterodactyl.php:132-145](file://DynamicPterodactyl.php#L132-L145) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) +- [DynamicPterodactyl.php:132-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L132-L145) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ResourceCalculationService.php:198-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L198-L214) **Section sources** -- [DynamicPterodactyl.php:132-145](file://DynamicPterodactyl.php#L132-L145) +- [DynamicPterodactyl.php:132-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L132-L145) ## Performance Considerations - Pessimistic locking: Reservation creation locks pending reservations per location to prevent races. @@ -426,10 +429,10 @@ Operational checks: - Inspect reservation statuses and expiration timestamps. **Section sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) ## Conclusion The extension implements a robust, event-driven checkout flow that reserves resources during cart operations, confirms them upon payment with real-time availability checks, and maintains comprehensive audit trails. Concurrency is handled through pessimistic locking and retries, while scheduled tasks ensure data consistency. This design balances reliability, performance, and observability across the payment and provisioning workflow. diff --git a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Payment and Service Events.md b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Payment and Service Events.md index f5c9c43..9d40f0d 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Payment and Service Events.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Event-Driven Architecture/Payment and Service Events.md @@ -1,20 +1,23 @@ # Payment and Service Events +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [InvoicePaidListener.php](file://Listeners/InvoicePaidListener.php) -- [ServiceCreatedListener.php](file://Listeners/ServiceCreatedListener.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [AlertService.php](file://Services/AlertService.php) -- [AuditLogService.php](file://Services/AuditLogService.php) -- [AuditsExtensionActions.php](file://Services/Concerns/AuditsExtensionActions.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [AuditLog.php](file://Models/AuditLog.php) -- [ReservationController.php](file://Http/Controllers/Api/ReservationController.php) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) -- [2025_01_01_000003_create_ptero_audit_logs_table.php](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) +- [InvoicePaidListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php) +- [ServiceCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) +- [AuditLogService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php) +- [AuditsExtensionActions.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [AuditLog.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php) +- [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) +- [2025_01_01_000003_create_ptero_audit_logs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) ## Table of Contents @@ -72,20 +75,20 @@ S4 --> D2 ``` **Diagram sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) -- [ReservationService.php:43-199](file://Services/ReservationService.php#L43-L199) -- [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) +- [ReservationService.php:43-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L199) +- [ResourceCalculationService.php:200-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L200-L214) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) **Section sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) -- [ReservationService.php:43-199](file://Services/ReservationService.php#L43-L199) -- [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) +- [ReservationService.php:43-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L199) +- [ResourceCalculationService.php:200-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L200-L214) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) ## Core Components - InvoicePaidListener: Orchestrates post-payment confirmation by retrieving the reservation token from the paid service, verifying current availability, confirming the reservation, and alerting on failures. @@ -102,16 +105,16 @@ Key responsibilities: - Ensure idempotent reservation creation via unique active idempotency keys. **Section sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ReservationService.php:43-199](file://Services/ReservationService.php#L43-L199) -- [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) -- [AuditsExtensionActions.php:10-32](file://Services/Concerns/AuditsExtensionActions.php#L10-L32) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-20](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L20) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ReservationService.php:43-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L199) +- [ResourceCalculationService.php:200-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L200-L214) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) +- [AuditsExtensionActions.php:10-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L32) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L20) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) ## Architecture Overview The payment-to-provisioning workflow uses event-driven processing with strong consistency guarantees at critical points. @@ -152,10 +155,10 @@ end ``` **Diagram sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ResourceCalculationService.php:200-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L200-L214) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) ## Detailed Component Analysis @@ -177,7 +180,7 @@ Failure handling: - All exceptions are caught and logged to ensure invoice processing continues even if one item fails. **Section sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) #### Sequence: Payment Confirmation Flow ```mermaid @@ -208,10 +211,10 @@ end ``` **Diagram sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ResourceCalculationService.php:200-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L200-L214) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) ### ReservationService: Idempotent Creation and State Transitions Responsibilities: @@ -237,11 +240,11 @@ Complexity considerations: - Deadlock scenarios are retried up to five times. **Section sources** -- [ReservationService.php:43-199](file://Services/ReservationService.php#L43-L199) -- [ReservationService.php:208-281](file://Services/ReservationService.php#L208-L281) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [ReservationService.php:431-452](file://Services/ReservationService.php#L431-L452) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-20](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L20) +- [ReservationService.php:43-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L199) +- [ReservationService.php:208-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L281) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [ReservationService.php:431-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L431-L452) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L20) #### Flowchart: Reservation Creation with Idempotency ```mermaid @@ -261,8 +264,8 @@ Audit --> Done(["Return reservation"]) ``` **Diagram sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:431-452](file://Services/ReservationService.php#L431-L452) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:431-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L431-L452) ### ResourceCalculationService: Real-Time Capacity Verification Responsibilities: @@ -279,9 +282,9 @@ API interaction: - Returns degraded snapshots when the API is unavailable for cluster-wide queries, but availability checks remain strict. **Section sources** -- [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:200-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L200-L214) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) ### AlertService: Shortfall Notifications Responsibilities: @@ -294,7 +297,7 @@ Notification flow: - Catch and log delivery failures without aborting the caller. **Section sources** -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) ### ServiceCreatedListener: Audit Trail Linking Responsibilities: @@ -305,7 +308,7 @@ Note: - The actual confirmation should already have occurred via InvoicePaidListener; this listener primarily supports observability and audit trails. **Section sources** -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) ### Audit Logging: Persistent Action History Responsibilities: @@ -317,9 +320,9 @@ Safety: - Failures are logged and reported safely. **Section sources** -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) -- [AuditsExtensionActions.php:10-32](file://Services/Concerns/AuditsExtensionActions.php#L10-L32) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) +- [AuditsExtensionActions.php:10-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L32) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) ### Data Model and Lifecycle Reservations track: @@ -329,8 +332,8 @@ Reservations track: Indexes support efficient queries for cleanup, location-based locking, and filtering. **Section sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) ## Dependency Analysis The following diagram shows how components depend on each other during payment confirmation and provisioning. @@ -348,11 +351,11 @@ AUD --> DB2["Audit Logs Table"] ``` **Diagram sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ReservationService.php:43-199](file://Services/ReservationService.php#L43-L199) -- [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ReservationService.php:43-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L199) +- [ResourceCalculationService.php:200-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L200-L214) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) Coupling and cohesion: - Listeners are thin orchestration layers delegating to focused services. @@ -371,10 +374,10 @@ Interface contracts: - confirm returns a boolean indicating whether a pending reservation was successfully transitioned. **Section sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ReservationService.php:43-199](file://Services/ReservationService.php#L43-L199) -- [ResourceCalculationService.php:200-214](file://Services/ResourceCalculationService.php#L200-L214) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ReservationService.php:43-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L199) +- [ResourceCalculationService.php:200-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L200-L214) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) ## Performance Considerations - Real-time availability checks: Every confirmation calls the Pterodactyl API to ensure accurate capacity. This avoids stale cache issues but introduces latency. @@ -421,11 +424,11 @@ Operational checks: - Review scheduled cleanup to ensure expired reservations are marked correctly. **Section sources** -- [InvoicePaidListener.php:43-133](file://Listeners/InvoicePaidListener.php#L43-L133) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) -- [ReservationService.php:125-141](file://Services/ReservationService.php#L125-L141) -- [ReservationService.php:431-452](file://Services/ReservationService.php#L431-L452) -- [AuditsExtensionActions.php:10-32](file://Services/Concerns/AuditsExtensionActions.php#L10-L32) +- [InvoicePaidListener.php:43-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L43-L133) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) +- [ReservationService.php:125-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L125-L141) +- [ReservationService.php:431-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L431-L452) +- [AuditsExtensionActions.php:10-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L32) ## Conclusion The payment and service event handling system ensures reliable reservation confirmation through real-time capacity verification, robust state transitions, and comprehensive auditing. Idempotency and retry mechanisms protect against duplicate operations and transient failures. Alerts provide visibility into capacity shortfalls and state drift, enabling timely operational intervention. The design emphasizes correctness and resilience while maintaining clear separation of concerns between event listeners, services, and data persistence. diff --git a/.qoder/repowiki/en/content/Architecture Overview/Real-Time Integration Strategy.md b/.qoder/repowiki/en/content/Architecture Overview/Real-Time Integration Strategy.md index 02ed419..9d5f987 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Real-Time Integration Strategy.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Real-Time Integration Strategy.md @@ -1,14 +1,17 @@ # Real-Time Integration Strategy +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) -- [api.php](file://routes/api.php) -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [ResourceCalculationServiceTest.php](file://tests/Unit/ResourceCalculationServiceTest.php) -- [08-ALGORITHMS.md](file://08-ALGORITHMS.md) -- [03-API.md](file://03-API.md) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) +- [api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [ResourceCalculationServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php) +- [08-ALGORITHMS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/08-ALGORITHMS.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/03-API.md) ## Table of Contents @@ -50,13 +53,13 @@ ResourceSvc --> DB ``` **Diagram sources** -- [api.php:17-25](file://routes/api.php#L17-L25) -- [AvailabilityController.php:22-51](file://Http/Controllers/Api/AvailabilityController.php#L22-L51) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [api.php:17-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L25) +- [AvailabilityController.php:22-51](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L51) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) **Section sources** -- [api.php:17-25](file://routes/api.php#L17-L25) -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) +- [api.php:17-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L25) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) ## Core Components - ResourceCalculationService: Centralizes all Pterodactyl API interactions, builds per-location and per-node availability, and constructs a full cluster snapshot without caching. It also implements robust HTTP retry, timeout, and error handling. @@ -72,11 +75,11 @@ Key responsibilities: - Return degraded snapshots when the panel is down **Section sources** -- [ResourceCalculationService.php:10-21](file://Services/ResourceCalculationService.php#L10-L21) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [AvailabilityController.php:22-51](file://Http/Controllers/Api/AvailabilityController.php#L22-L51) -- [api.php:17-25](file://routes/api.php#L17-L25) +- [ResourceCalculationService.php:10-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L10-L21) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [AvailabilityController.php:22-51](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L51) +- [api.php:17-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L25) ## Architecture Overview The system uses a real-time, non-cached approach to ensure accurate availability at every step of the customer journey. @@ -99,11 +102,11 @@ A-->>C : Aggregate capacity response ``` **Diagram sources** -- [api.php:17-25](file://routes/api.php#L17-L25) -- [AvailabilityController.php:22-51](file://Http/Controllers/Api/AvailabilityController.php#L22-L51) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceCalculationService.php:226-245](file://Services/ResourceCalculationService.php#L226-L245) -- [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) +- [api.php:17-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L25) +- [AvailabilityController.php:22-51](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L51) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceCalculationService.php:226-245](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L226-L245) +- [ResourceCalculationService.php:426-450](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L450) ## Detailed Component Analysis @@ -113,8 +116,8 @@ A-->>C : Aggregate capacity response - Customer-facing endpoints return only aggregated per-location maxima; node-level detail is admin-only. **Section sources** -- [08-ALGORITHMS.md:357-367](file://08-ALGORITHMS.md#L357-L367) -- [AvailabilityController.php:22-51](file://Http/Controllers/Api/AvailabilityController.php#L22-L51) +- [08-ALGORITHMS.md:357-367](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/08-ALGORITHMS.md#L357-L367) +- [AvailabilityController.php:22-51](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L51) ### Batching in buildClusterSnapshot() buildClusterSnapshot() minimizes API calls while maintaining accuracy: @@ -141,14 +144,14 @@ Pending --> ForEachNode --> Aggregate --> Return ``` **Diagram sources** -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [ResourceCalculationService.php:302-357](file://Services/ResourceCalculationService.php#L302-L357) -- [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [ResourceCalculationService.php:302-357](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L302-L357) +- [ResourceCalculationService.php:426-450](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L450) **Section sources** -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [ResourceCalculationService.php:302-357](file://Services/ResourceCalculationService.php#L302-L357) -- [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [ResourceCalculationService.php:302-357](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L302-L357) +- [ResourceCalculationService.php:426-450](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L450) ### HTTP Client, Timeouts, Retries, and Error Handling All outbound requests go through a centralized helper that: @@ -185,7 +188,7 @@ Validate --> |No| ThrowErr ``` **Diagram sources** -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) Error scenarios covered: - Authentication failures: handled by Pterodactyl returning client errors; these are reported and thrown as runtime exceptions with sanitized messages @@ -195,12 +198,12 @@ Error scenarios covered: - Degraded snapshot: when the panel returns server errors, buildClusterSnapshot returns an empty snapshot marked as unavailable instead of crashing the caller **Section sources** -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ResourceCalculationService.php:410-424](file://Services/ResourceCalculationService.php#L410-L424) -- [ResourceCalculationService.php:69-82](file://Services/ResourceCalculationService.php#L69-L82) -- [ResourceCalculationServiceTest.php:53-84](file://tests/Unit/ResourceCalculationServiceTest.php#L53-L84) -- [ResourceCalculationServiceTest.php:86-123](file://tests/Unit/ResourceCalculationServiceTest.php#L86-L123) -- [ResourceCalculationServiceTest.php:125-139](file://tests/Unit/ResourceCalculationServiceTest.php#L125-L139) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:410-424](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L410-L424) +- [ResourceCalculationService.php:69-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L82) +- [ResourceCalculationServiceTest.php:53-84](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L53-L84) +- [ResourceCalculationServiceTest.php:86-123](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L86-L123) +- [ResourceCalculationServiceTest.php:125-139](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L125-L139) ### Connection Pooling and Request Batching - Connection pooling: Uses the framework’s HTTP client, which reuses connections by default. This reduces TCP handshake overhead for repeated calls within a request lifecycle. @@ -213,10 +216,10 @@ Error scenarios covered: These choices keep the number of API calls constant regardless of cluster size, as verified by tests asserting bounded call counts even with many nodes. **Section sources** -- [ResourceCalculationService.php:291-384](file://Services/ResourceCalculationService.php#L291-L384) -- [ResourceCalculationService.php:302-357](file://Services/ResourceCalculationService.php#L302-L357) -- [ResourceCalculationServiceTest.php:195-221](file://tests/Unit/ResourceCalculationServiceTest.php#L195-L221) -- [ResourceCalculationServiceTest.php:307-332](file://tests/Unit/ResourceCalculationServiceTest.php#L307-L332) +- [ResourceCalculationService.php:291-384](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L291-L384) +- [ResourceCalculationService.php:302-357](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L302-L357) +- [ResourceCalculationServiceTest.php:195-221](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L195-L221) +- [ResourceCalculationServiceTest.php:307-332](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L307-L332) ### Monitoring and Logging - Internal diagnostics: Full upstream error bodies are reported for observability without leaking sensitive details to callers @@ -231,10 +234,10 @@ Operational recommendations: - Correlate dashboard health banners with connection test results **Section sources** -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) -- [api.php:17-25](file://routes/api.php#L17-L25) -- [DynamicPterodactyl.php:116-127](file://DynamicPterodactyl.php#L116-L127) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) +- [api.php:17-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L25) +- [DynamicPterodactyl.php:116-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L116-L127) ## Dependency Analysis The real-time integration depends on: @@ -254,12 +257,12 @@ HC --> PA ``` **Diagram sources** -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:426-450](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L450) **Section sources** -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:426-450](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L450) ## Performance Considerations - Timeouts: Per-attempt timeouts and connect timeouts prevent long hangs; retries are limited to transient connection issues @@ -285,9 +288,9 @@ Verification steps: - Confirm throttling settings align with Pterodactyl API limits **Section sources** -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [03-API.md:677-721](file://03-API.md#L677-L721) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [03-API.md:677-721](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/03-API.md#L677-L721) ## Conclusion This extension integrates with Pterodactyl using a strict real-time strategy: no caching, direct API reads, and careful batching to balance accuracy and performance. Robust error handling ensures graceful degradation when the panel is unavailable, while throttling and timeouts protect both systems under load. Operational monitoring and logging provide visibility into API health and performance, enabling proactive management of capacity and reliability. diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md index c843445..fd22dc3 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Node Selection Service.md @@ -1,14 +1,17 @@ # Node Selection Service +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [NodeSelectionService.php](file://Services/NodeSelectionService.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [NodeSelectionServiceTest.php](file://tests/Unit/NodeSelectionServiceTest.php) -- [ResourceCalculationServiceTest.php](file://tests/Unit/ResourceCalculationServiceTest.php) -- [2026_04_22_000001_drop_released_from_reservation_status.php](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) +- [NodeSelectionService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [NodeSelectionServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/NodeSelectionServiceTest.php) +- [ResourceCalculationServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php) +- [2026_04_22_000001_drop_released_from_reservation_status.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) ## Table of Contents @@ -43,15 +46,15 @@ RCSvc --> DB ``` **Diagram sources** -- [ReservationService.php:43-124](file://Services/ReservationService.php#L43-L124) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [ReservationService.php:43-124](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L124) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) **Section sources** -- [NodeSelectionService.php:1-88](file://Services/NodeSelectionService.php#L1-L88) -- [ResourceCalculationService.php:1-545](file://Services/ResourceCalculationService.php#L1-L545) -- [ReservationService.php:1-453](file://Services/ReservationService.php#L1-L453) -- [ResourceReservation.php:1-65](file://Models/ResourceReservation.php#L1-L65) +- [NodeSelectionService.php:1-88](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L1-L88) +- [ResourceCalculationService.php:1-545](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L1-L545) +- [ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) +- [ResourceReservation.php:1-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L1-L65) ## Core Components - NodeSelectionService: Selects the best node using weighted headroom scoring and filters out unsuitable nodes (maintenance mode or insufficient resources). @@ -64,10 +67,10 @@ Key responsibilities: - Concurrency safety: ReservationService uses lockForUpdate on pending reservations within a transaction and retries on deadlock. **Section sources** -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceCalculationService.php:146-289](file://Services/ResourceCalculationService.php#L146-L289) -- [ReservationService.php:43-124](file://Services/ReservationService.php#L43-L124) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceCalculationService.php:146-289](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L146-L289) +- [ReservationService.php:43-124](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L124) ## Architecture Overview The selection flow is driven by ReservationService when creating a reservation: @@ -105,10 +108,10 @@ R->>D : COMMIT ``` **Diagram sources** -- [ReservationService.php:43-124](file://Services/ReservationService.php#L43-L124) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [ReservationService.php:43-124](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L124) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) ## Detailed Component Analysis @@ -145,7 +148,7 @@ Sort --> ReturnBest["Return best node"] ``` **Diagram sources** -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) Edge cases handled: - Insufficient capacity: If no node can fit the request, returns null. @@ -154,14 +157,14 @@ Edge cases handled: - Dynamic resource changes: Uses real-time availability; decisions reflect current cluster state. **Section sources** -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [NodeSelectionServiceTest.php:32-70](file://tests/Unit/NodeSelectionServiceTest.php#L32-L70) -- [NodeSelectionServiceTest.php:75-112](file://tests/Unit/NodeSelectionServiceTest.php#L75-L112) -- [NodeSelectionServiceTest.php:117-154](file://tests/Unit/NodeSelectionServiceTest.php#L117-L154) -- [NodeSelectionServiceTest.php:159-195](file://tests/Unit/NodeSelectionServiceTest.php#L159-L195) -- [NodeSelectionServiceTest.php:200-236](file://tests/Unit/NodeSelectionServiceTest.php#L200-L236) -- [NodeSelectionServiceTest.php:241-267](file://tests/Unit/NodeSelectionServiceTest.php#L241-L267) -- [NodeSelectionServiceTest.php:272-311](file://tests/Unit/NodeSelectionServiceTest.php#L272-L311) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [NodeSelectionServiceTest.php:32-70](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/NodeSelectionServiceTest.php#L32-L70) +- [NodeSelectionServiceTest.php:75-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/NodeSelectionServiceTest.php#L75-L112) +- [NodeSelectionServiceTest.php:117-154](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/NodeSelectionServiceTest.php#L117-L154) +- [NodeSelectionServiceTest.php:159-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/NodeSelectionServiceTest.php#L159-L195) +- [NodeSelectionServiceTest.php:200-236](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/NodeSelectionServiceTest.php#L200-L236) +- [NodeSelectionServiceTest.php:241-267](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/NodeSelectionServiceTest.php#L241-L267) +- [NodeSelectionServiceTest.php:272-311](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/NodeSelectionServiceTest.php#L272-L311) ### ResourceCalculationService: Real-Time Availability - Purpose: Provide accurate, up-to-date availability for nodes and locations. @@ -189,18 +192,18 @@ class ResourceCalculationService { ``` **Diagram sources** -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceCalculationService.php:146-289](file://Services/ResourceCalculationService.php#L146-L289) -- [ResourceCalculationService.php:500-522](file://Services/ResourceCalculationService.php#L500-L522) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceCalculationService.php:146-289](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L146-L289) +- [ResourceCalculationService.php:500-522](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L500-L522) How it supports NodeSelectionService: - Supplies per-node available and total capacities, including maintenance flags. - Ensures pending reservations reduce available resources so selections account for concurrent allocations. **Section sources** -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceCalculationService.php:146-289](file://Services/ResourceCalculationService.php#L146-L289) -- [ResourceCalculationService.php:500-522](file://Services/ResourceCalculationService.php#L500-L522) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceCalculationService.php:146-289](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L146-L289) +- [ResourceCalculationService.php:500-522](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L500-L522) ### ReservationService: Creation Flow and Concurrency - Transactional creation: @@ -231,17 +234,17 @@ R->>D : COMMIT ``` **Diagram sources** -- [ReservationService.php:43-124](file://Services/ReservationService.php#L43-L124) +- [ReservationService.php:43-124](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L124) Integration with ResourceCalculationService: - NodeSelectionService depends on ResourceCalculationService for live availability, ensuring selection decisions are based on current cluster state rather than historical patterns. **Section sources** -- [ReservationService.php:43-124](file://Services/ReservationService.php#L43-L124) -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ReservationService.php:250-281](file://Services/ReservationService.php#L250-L281) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) +- [ReservationService.php:43-124](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L124) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ReservationService.php:250-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L250-L281) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) ### ResourceReservation Model and Status Flow - Fields include token, idempotency_key, node_id, location_id, resource amounts, pricing, status, and expires_at. @@ -257,12 +260,12 @@ Pending --> Cancelled : "cancel(token)" ``` **Diagram sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-19](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L19) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-19](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L19) **Section sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-19](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L19) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-19](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L19) ## Dependency Analysis - NodeSelectionService depends on ResourceCalculationService for real-time availability. @@ -279,14 +282,14 @@ ReservationService --> DB ``` **Diagram sources** -- [ReservationService.php:20-27](file://Services/ReservationService.php#L20-L27) -- [NodeSelectionService.php:7-12](file://Services/NodeSelectionService.php#L7-L12) -- [ResourceCalculationService.php:12-21](file://Services/ResourceCalculationService.php#L12-L21) +- [ReservationService.php:20-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L20-L27) +- [NodeSelectionService.php:7-12](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L7-L12) +- [ResourceCalculationService.php:12-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L12-L21) **Section sources** -- [ReservationService.php:20-27](file://Services/ReservationService.php#L20-L27) -- [NodeSelectionService.php:7-12](file://Services/NodeSelectionService.php#L7-L12) -- [ResourceCalculationService.php:12-21](file://Services/ResourceCalculationService.php#L12-L21) +- [ReservationService.php:20-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L20-L27) +- [NodeSelectionService.php:7-12](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L7-L12) +- [ResourceCalculationService.php:12-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L12-L21) ## Performance Considerations - Real-time API calls: ResourceCalculationService avoids caching Pterodactyl responses; this ensures accuracy but introduces latency proportional to the number of nodes and servers. @@ -315,9 +318,9 @@ Relevant behaviors: - Deadlock retries protect reservation creation under load. **Section sources** -- [ReservationService.php:75-79](file://Services/ReservationService.php#L75-L79) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ResourceCalculationServiceTest.php:175-193](file://tests/Unit/ResourceCalculationServiceTest.php#L175-L193) +- [ReservationService.php:75-79](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L75-L79) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationServiceTest.php:175-193](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L175-L193) ## Conclusion NodeSelectionService implements a robust weighted best-fit algorithm that balances load distribution and avoids hotspots by prioritizing memory headroom, then disk, then CPU. It relies on ResourceCalculationService for real-time availability, ensuring decisions reflect the current cluster state. ReservationService orchestrates creation with strong concurrency controls, maintaining a strict reservation lifecycle. Together, these components provide reliable, scalable resource allocation across Pterodactyl nodes. diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Reservation Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Reservation Service.md index bc2447a..b8ed8c4 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Reservation Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Reservation Service.md @@ -1,18 +1,21 @@ # Reservation Service +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [ReservationService.php](file://Services/ReservationService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [NodeSelectionService.php](file://Services/NodeSelectionService.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [CartItemCreatedListener.php](file://Listeners/CartItemCreatedListener.php) -- [InvoicePaidListener.php](file://Listeners/InvoicePaidListener.php) -- [ReservationController.php](file://Http/Controllers/Api/ReservationController.php) -- [ResourceReservationPolicy.php](file://Policies/ResourceReservationPolicy.php) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) -- [2026_04_22_000001_drop_released_from_reservation_status.php](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [NodeSelectionService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php) +- [InvoicePaidListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php) +- [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) +- [ResourceReservationPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) +- [2026_04_22_000001_drop_released_from_reservation_status.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) ## Table of Contents @@ -55,25 +58,25 @@ Policy -.-> Service ``` **Diagram sources** -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [ReservationService.php:43-453](file://Services/ReservationService.php#L43-L453) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [ReservationService.php:43-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L453) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ResourceReservationPolicy.php:14-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L68) **Section sources** -- [ReservationService.php:17-453](file://Services/ReservationService.php#L17-L453) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [NodeSelectionService.php:5-86](file://Services/NodeSelectionService.php#L5-L86) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-25](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L25) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-29](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L29) +- [ReservationService.php:17-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L17-L453) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [NodeSelectionService.php:5-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L5-L86) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [ResourceReservationPolicy.php:14-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L68) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L25) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-29](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L29) ## Core Components - ReservationService: Creates, confirms, cancels, extends, queries, and cleans up reservations. Uses pessimistic locking, transaction retries, idempotency keys, and TTL expiration. @@ -92,16 +95,16 @@ Key responsibilities: - Idempotency: Detect duplicates via unique active idempotency key constraint and handle race safely. **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L281) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [ResourceReservationPolicy.php:14-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L68) ## Architecture Overview The reservation architecture integrates event-driven creation, real-time availability checks, and strict state transitions: @@ -140,11 +143,11 @@ end ``` **Diagram sources** -- [CartItemCreatedListener.php:47-87](file://Listeners/CartItemCreatedListener.php#L47-L87) -- [ReservationService.php:52-124](file://Services/ReservationService.php#L52-L124) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [InvoicePaidListener.php:58-96](file://Listeners/InvoicePaidListener.php#L58-L96) +- [CartItemCreatedListener.php:47-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L47-L87) +- [ReservationService.php:52-124](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L52-L124) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [InvoicePaidListener.php:58-96](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L58-L96) ## Detailed Component Analysis @@ -204,16 +207,16 @@ Rollback --> End ``` **Diagram sources** -- [ReservationService.php:52-124](file://Services/ReservationService.php#L52-L124) -- [ReservationService.php:431-442](file://Services/ReservationService.php#L431-L442) -- [ReservationService.php:444-452](file://Services/ReservationService.php#L444-L452) +- [ReservationService.php:52-124](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L52-L124) +- [ReservationService.php:431-442](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L431-L442) +- [ReservationService.php:444-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L444-L452) **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) -- [ReservationService.php:286-382](file://Services/ReservationService.php#L286-L382) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [ReservationService.php:407-453](file://Services/ReservationService.php#L407-L453) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L281) +- [ReservationService.php:286-382](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L286-L382) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [ReservationService.php:407-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L407-L453) ### NodeSelectionService Responsibilities: @@ -244,10 +247,10 @@ Next --> Iterate ``` **Diagram sources** -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) **Section sources** -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) ### ResourceCalculationService Responsibilities: @@ -278,15 +281,15 @@ ResSvc-->>Caller : locationData with nodes, max_available, totals ``` **Diagram sources** -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) -- [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) +- [ResourceCalculationService.php:426-450](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L450) **Section sources** -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) -- [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceCalculationService.php:198-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L198-L214) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) +- [ResourceCalculationService.php:426-450](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L450) ### Data Model and Migration Evolution - Initial schema includes token, references to cart/service/user/node/location, resource fields, pricing snapshot, status enum including released, timestamps, indexes, and foreign keys. @@ -319,14 +322,14 @@ timestamp updated_at ``` **Diagram sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-25](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L25) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-29](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L29) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L25) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-29](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L29) **Section sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-25](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L25) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-29](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L29) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L25) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-29](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L29) ### Event Integration Examples @@ -350,12 +353,12 @@ Listener->>Listener : store token in checkout_config ``` **Diagram sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [ReservationService.php:52-124](file://Services/ReservationService.php#L52-L124) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [ReservationService.php:52-124](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L52-L124) **Section sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [ReservationService.php:52-124](file://Services/ReservationService.php#L52-L124) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [ReservationService.php:52-124](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L52-L124) #### Confirmation During Payment Processing - On invoice paid, the listener retrieves the reservation token from service properties. @@ -384,14 +387,14 @@ end ``` **Diagram sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ResourceCalculationService.php:198-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L198-L214) **Section sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ResourceCalculationService.php:198-214](file://Services/ResourceCalculationService.php#L198-L214) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ResourceCalculationService.php:198-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L198-L214) #### Cancellation Scenarios - User or admin can cancel a pending reservation via API or internal flow. @@ -415,14 +418,14 @@ Controller-->>Client : response ``` **Diagram sources** -- [ReservationController.php:81-99](file://Http/Controllers/Api/ReservationController.php#L81-L99) -- [ResourceReservationPolicy.php:37-40](file://Policies/ResourceReservationPolicy.php#L37-L40) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) +- [ReservationController.php:81-99](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L81-L99) +- [ResourceReservationPolicy.php:37-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L37-L40) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) **Section sources** -- [ReservationController.php:81-99](file://Http/Controllers/Api/ReservationController.php#L81-L99) -- [ResourceReservationPolicy.php:37-40](file://Policies/ResourceReservationPolicy.php#L37-L40) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) +- [ReservationController.php:81-99](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L81-L99) +- [ResourceReservationPolicy.php:37-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L37-L40) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) ## Dependency Analysis - ReservationService depends on: @@ -448,18 +451,18 @@ ReservationController --> ResourceReservationPolicy ``` **Diagram sources** -- [ReservationService.php:20-35](file://Services/ReservationService.php#L20-L35) -- [NodeSelectionService.php:7-12](file://Services/NodeSelectionService.php#L7-L12) -- [CartItemCreatedListener.php:47-87](file://Listeners/CartItemCreatedListener.php#L47-L87) -- [InvoicePaidListener.php:37-96](file://Listeners/InvoicePaidListener.php#L37-L96) -- [ReservationController.php:17-22](file://Http/Controllers/Api/ReservationController.php#L17-L22) +- [ReservationService.php:20-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L20-L35) +- [NodeSelectionService.php:7-12](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L7-L12) +- [CartItemCreatedListener.php:47-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L47-L87) +- [InvoicePaidListener.php:37-96](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L37-L96) +- [ReservationController.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L17-L22) **Section sources** -- [ReservationService.php:20-35](file://Services/ReservationService.php#L20-L35) -- [NodeSelectionService.php:7-12](file://Services/NodeSelectionService.php#L7-L12) -- [CartItemCreatedListener.php:47-87](file://Listeners/CartItemCreatedListener.php#L47-L87) -- [InvoicePaidListener.php:37-96](file://Listeners/InvoicePaidListener.php#L37-L96) -- [ReservationController.php:17-22](file://Http/Controllers/Api/ReservationController.php#L17-L22) +- [ReservationService.php:20-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L20-L35) +- [NodeSelectionService.php:7-12](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L7-L12) +- [CartItemCreatedListener.php:47-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L47-L87) +- [InvoicePaidListener.php:37-96](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L37-L96) +- [ReservationController.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L17-L22) ## Performance Considerations - Pessimistic locking with lockForUpdate() serializes concurrent modifications to pending reservations per location, preventing race conditions during checkout. @@ -490,11 +493,11 @@ Operational tips: - Validate configuration settings for reservation_ttl and Pterodactyl API connectivity. **Section sources** -- [ReservationService.php:125-141](file://Services/ReservationService.php#L125-L141) -- [ReservationService.php:444-452](file://Services/ReservationService.php#L444-L452) -- [ReservationController.php:49-59](file://Http/Controllers/Api/ReservationController.php#L49-L59) -- [InvoicePaidListener.php:65-125](file://Listeners/InvoicePaidListener.php#L65-L125) -- [ResourceReservationPolicy.php:28-58](file://Policies/ResourceReservationPolicy.php#L28-L58) +- [ReservationService.php:125-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L125-L141) +- [ReservationService.php:444-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L444-L452) +- [ReservationController.php:49-59](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L49-L59) +- [InvoicePaidListener.php:65-125](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L65-L125) +- [ResourceReservationPolicy.php:28-58](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L28-L58) ## Conclusion The ReservationService provides a robust, concurrency-safe mechanism for reserving Pterodactyl node resources during checkout. Its strict state machine, pessimistic locking, idempotency support, and integration with event-driven workflows ensure reliable capacity management. By coordinating with NodeSelectionService and ResourceCalculationService, it assigns optimal nodes and verifies availability at critical points. The removal of the 'released' state simplifies lifecycle semantics, focusing on pending, confirmed, expired, and cancelled states. Operational visibility through auditing and alerts helps maintain system health and responsiveness. diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md index 8bbb41e..cbd0df4 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Resource Calculation Service.md @@ -1,13 +1,16 @@ # Resource Calculation Service +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) -- [NodeSelectionService.php](file://Services/NodeSelectionService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [DECISIONS.md](file://DECISIONS.md) -- [ResourceCalculationServiceTest.php](file://tests/Unit/ResourceCalculationServiceTest.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) +- [NodeSelectionService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md) +- [ResourceCalculationServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php) ## Table of Contents @@ -42,14 +45,14 @@ NSS --> RCS ``` **Diagram sources** -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [ResourceCalculationService.php:26-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L141) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) **Section sources** -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [ResourceCalculationService.php:26-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L141) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) ## Core Components - ResourceCalculationService: Real-time availability calculations against Pterodactyl, including node and location aggregation, pending reservation accounting, and cluster snapshot building. @@ -64,10 +67,10 @@ Key responsibilities: - Provide admin-only detailed node data via separate routes (not covered here). **Section sources** -- [ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [ResourceCalculationService.php:26-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L141) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ## Architecture Overview The service follows a real-time architecture: @@ -95,9 +98,9 @@ A-->>C : {has_capacity, max_memory/cpu/disk, node_count} ``` **Diagram sources** -- [AvailabilityController.php:22-51](file://Http/Controllers/Api/AvailabilityController.php#L22-L51) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) +- [AvailabilityController.php:22-51](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L51) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [ResourceCalculationService.php:26-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L141) ## Detailed Component Analysis @@ -136,13 +139,13 @@ LoopNodes --> |No| ReturnLoc["Return location data"] ``` **Diagram sources** -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) **Section sources** -- [ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) -- [ResourceCalculationService.php:146-214](file://Services/ResourceCalculationService.php#L146-L214) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:26-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L141) +- [ResourceCalculationService.php:146-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L146-L214) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) ### AvailabilityController Exposes customer-facing availability endpoints: @@ -156,7 +159,7 @@ Security and privacy: - Customer endpoints do not expose raw node names, FQDNs, maintenance flags, or per-node capacity; only aggregated maxima are returned. **Section sources** -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) ### NodeSelectionService Implements best-fit node selection with weighted headroom: @@ -164,13 +167,13 @@ Implements best-fit node selection with weighted headroom: - getMaxAvailable(locationId): Delegates to ResourceCalculationService to obtain per-location maximum available resources. **Section sources** -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) ### ResourceReservation Model Represents pending reservations with fields for token, idempotency key, user/service references, node/location IDs, requested resources, pricing metadata, status, notes, and expiration. Scopes provide convenient queries for pending and expired reservations used by availability calculations. **Section sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ## Dependency Analysis - AvailabilityController depends on ResourceCalculationService and NodeSelectionService to compose customer-facing responses. @@ -208,16 +211,16 @@ ResourceCalculationService --> ResourceReservation : "reads pending" ``` **Diagram sources** -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [ResourceCalculationService.php:26-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L141) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) **Section sources** -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [ResourceCalculationService.php:26-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L141) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ## Performance Considerations - Real-time API calls: No caching ensures accuracy but introduces latency. Each availability check hits Pterodactyl directly. @@ -244,10 +247,10 @@ Operational tips: - When debugging availability discrepancies, inspect pending reservations in the local database and confirm their status and expiration. **Section sources** -- [ResourceCalculationService.php:157-195](file://Services/ResourceCalculationService.php#L157-L195) -- [ResourceCalculationService.php:487-631](file://Services/ResourceCalculationService.php#L487-L631) -- [ResourceCalculationService.php:426-470](file://Services/ResourceCalculationService.php#L426-L470) -- [ResourceCalculationServiceTest.php:53-139](file://tests/Unit/ResourceCalculationServiceTest.php#L53-L139) +- [ResourceCalculationService.php:157-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L157-L195) +- [ResourceCalculationService.php:487-631](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L487-L631) +- [ResourceCalculationService.php:426-470](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L470) +- [ResourceCalculationServiceTest.php:53-139](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L53-L139) ## Conclusion ResourceCalculationService delivers accurate, real-time resource availability by querying Pterodactyl directly and incorporating pending reservations. Its architectural decision to avoid caching prevents staleness and overselling risks. Key methods provide flexible views: diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md index d4bdb90..a6a1f26 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Service Layer Design.md @@ -1,16 +1,19 @@ # Service Layer Design +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [NodeSelectionService.php](file://Services/NodeSelectionService.php) -- [AlertService.php](file://Services/AlertService.php) -- [AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) -- [ReservationController.php](file://Http/Controllers/Api/ReservationController.php) -- [AdminCapacityController.php](file://Http/Controllers/Api/Admin/AdminCapacityController.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [NodeSelectionService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php) +- [AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) +- [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) +- [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) +- [AdminCapacityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) ## Table of Contents @@ -52,15 +55,15 @@ ResCalcSvc --> DB ``` **Diagram sources** -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [AdminCapacityController.php:17-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [AdminCapacityController.php:17-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [ResourceCalculationService.php:26-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L141) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) ## Core Components - ResourceCalculationService: Encapsulates all Pterodactyl API interactions, builds real-time availability snapshots, and aggregates per-location and per-node metrics. It never caches responses; it batches API calls where possible and degrades gracefully when the upstream is unavailable. @@ -70,13 +73,13 @@ ResCalcSvc --> DB - Controllers: Thin HTTP boundaries that validate input, enforce authorization, and call services. They translate exceptions into user-friendly JSON responses. **Section sources** -- [ResourceCalculationService.php:10-222](file://Services/ResourceCalculationService.php#L10-L222) -- [NodeSelectionService.php:5-86](file://Services/NodeSelectionService.php#L5-L86) -- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) -- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) -- [AvailabilityController.php:9-71](file://Http/Controllers/Api/AvailabilityController.php#L9-L71) -- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [AdminCapacityController.php:8-62](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) +- [ResourceCalculationService.php:10-222](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L10-L222) +- [NodeSelectionService.php:5-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L5-L86) +- [ReservationService.php:16-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L453) +- [AlertService.php:19-392](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L19-L392) +- [AvailabilityController.php:9-71](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L9-L71) +- [ReservationController.php:13-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminCapacityController.php:8-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) ## Architecture Overview The service layer enforces strict boundaries: @@ -103,10 +106,10 @@ A-->>C : {max_memory,max_cpu,max_disk,...} ``` **Diagram sources** -- [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [NodeSelectionService.php:81-86](file://Services/NodeSelectionService.php#L81-L86) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceCalculationService.php:359-384](file://Services/ResourceCalculationService.php#L359-L384) +- [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [NodeSelectionService.php:81-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L81-L86) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceCalculationService.php:359-384](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L359-L384) ## Detailed Component Analysis @@ -139,14 +142,14 @@ Aggregate --> Return(["Return location data"]) ``` **Diagram sources** -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceCalculationService.php:146-152](file://Services/ResourceCalculationService.php#L146-L152) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceCalculationService.php:146-152](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L146-L152) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) **Section sources** -- [ResourceCalculationService.php:26-222](file://Services/ResourceCalculationService.php#L26-L222) -- [ResourceCalculationService.php:291-384](file://Services/ResourceCalculationService.php#L291-L384) -- [ResourceCalculationService.php:410-498](file://Services/ResourceCalculationService.php#L410-L498) +- [ResourceCalculationService.php:26-222](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L222) +- [ResourceCalculationService.php:291-384](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L291-L384) +- [ResourceCalculationService.php:410-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L410-L498) ### NodeSelectionService Responsibilities: @@ -171,10 +174,10 @@ Choose -- "Yes" --> Best["Return top node"] ``` **Diagram sources** -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) **Section sources** -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) ### ReservationService Responsibilities: @@ -218,15 +221,15 @@ end ``` **Diagram sources** -- [ReservationController.php:24-60](file://Http/Controllers/Api/ReservationController.php#L24-L60) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [ReservationController.php:24-60](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L60) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) -- [ReservationService.php:387-453](file://Services/ReservationService.php#L387-L453) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L281) +- [ReservationService.php:387-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L453) ### AlertService Responsibilities: @@ -239,9 +242,9 @@ Error handling: - Emits an event when all channels fail to deliver. **Section sources** -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) ### Controllers and Boundaries - AvailabilityController: Returns aggregate capacity and node counts for customer-facing endpoints. It does not expose raw node identifiers or per-node capacities. @@ -249,9 +252,9 @@ Error handling: - AdminCapacityController: Builds a full cluster snapshot for administrative use, including node-level details. **Section sources** -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [AdminCapacityController.php:17-61](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [AdminCapacityController.php:17-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L61) ## Dependency Analysis Service composition and coupling: @@ -299,15 +302,15 @@ AdminCapacityController --> ResourceCalculationService : "uses" ``` **Diagram sources** -- [NodeSelectionService.php:5-86](file://Services/NodeSelectionService.php#L5-L86) -- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) -- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) -- [AvailabilityController.php:9-71](file://Http/Controllers/Api/AvailabilityController.php#L9-L71) -- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [AdminCapacityController.php:8-62](file://Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) +- [NodeSelectionService.php:5-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L5-L86) +- [ReservationService.php:16-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L453) +- [AlertService.php:19-392](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L19-L392) +- [AvailabilityController.php:9-71](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L9-L71) +- [ReservationController.php:13-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminCapacityController.php:8-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L8-L62) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) ## Performance Considerations - Real-time availability: All availability data is fetched live from Pterodactyl; there is no caching. This ensures accuracy but increases dependency on upstream latency. @@ -335,11 +338,11 @@ Common issues and where to look: - AlertService logs channel-specific failures and emits events when all channels fail. Inspect delivery logs and recipient configurations. **Section sources** -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L281) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) ## Conclusion The service layer cleanly separates concerns: diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Supporting Services.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Supporting Services.md index 7c1bd63..cd99ddd 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Supporting Services.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Supporting Services.md @@ -1,15 +1,18 @@ # Supporting Services +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [AuditLogService.php](file://Services/AuditLogService.php) -- [ConfigOptionSetupService.php](file://Services/ConfigOptionSetupService.php) -- [SliderConfigReaderService.php](file://Services/SliderConfigReaderService.php) -- [AuditsExtensionActions.php](file://Services/Concerns/AuditsExtensionActions.php) -- [AuditLog.php](file://Models/AuditLog.php) -- [2025_01_01_000003_create_ptero_audit_logs_table.php](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) -- [PricingController.php](file://Http/Controllers/Api/PricingController.php) -- [AuditLogPage.php](file://Admin/Pages/AuditLogPage.php) +- [AuditLogService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php) +- [ConfigOptionSetupService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php) +- [SliderConfigReaderService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php) +- [AuditsExtensionActions.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php) +- [AuditLog.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php) +- [2025_01_01_000003_create_ptero_audit_logs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) +- [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) +- [AuditLogPage.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php) ## Table of Contents @@ -64,20 +67,20 @@ A --> I ``` **Diagram sources** -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) -- [ConfigOptionSetupService.php:44-77](file://Services/ConfigOptionSetupService.php#L44-L77) -- [SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) -- [PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) -- [AuditLogPage.php:31-80](file://Admin/Pages/AuditLogPage.php#L31-L80) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) +- [ConfigOptionSetupService.php:44-77](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L77) +- [SliderConfigReaderService.php:14-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L53) +- [PricingController.php:24-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L145) +- [AuditLogPage.php:31-80](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L80) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) **Section sources** -- [AuditLogService.php:1-82](file://Services/AuditLogService.php#L1-L82) -- [ConfigOptionSetupService.php:1-259](file://Services/ConfigOptionSetupService.php#L1-L259) -- [SliderConfigReaderService.php:1-68](file://Services/SliderConfigReaderService.php#L1-L68) -- [PricingController.php:1-157](file://Http/Controllers/Api/PricingController.php#L1-L157) -- [AuditLogPage.php:1-104](file://Admin/Pages/AuditLogPage.php#L1-L104) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:1-54](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L1-L54) +- [AuditLogService.php:1-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L1-L82) +- [ConfigOptionSetupService.php:1-259](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L1-L259) +- [SliderConfigReaderService.php:1-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L1-L68) +- [PricingController.php:1-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L1-L157) +- [AuditLogPage.php:1-104](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L1-L104) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:1-54](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L1-L54) ## Core Components - AuditLogService: Provides methods to log actions and retrieve filtered logs. Captures user context, request metadata, and before/after values for changes. @@ -90,9 +93,9 @@ Key responsibilities: - Expose slider configuration to clients without exposing internal pricing logic. **Section sources** -- [AuditLogService.php:15-81](file://Services/AuditLogService.php#L15-L81) -- [ConfigOptionSetupService.php:44-171](file://Services/ConfigOptionSetupService.php#L44-L171) -- [SliderConfigReaderService.php:14-66](file://Services/SliderConfigReaderService.php#L14-L66) +- [AuditLogService.php:15-81](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L81) +- [ConfigOptionSetupService.php:44-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L171) +- [SliderConfigReaderService.php:14-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L66) ## Architecture Overview The supporting services form a clear separation of concerns: @@ -118,10 +121,10 @@ Setup-->>Admin : created option ids ``` **Diagram sources** -- [ConfigOptionSetupService.php:44-77](file://Services/ConfigOptionSetupService.php#L44-L77) -- [AuditsExtensionActions.php:10-32](file://Services/Concerns/AuditsExtensionActions.php#L10-L32) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [ConfigOptionSetupService.php:44-77](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L77) +- [AuditsExtensionActions.php:10-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L32) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) ## Detailed Component Analysis @@ -152,18 +155,18 @@ ReturnId --> End(["Done"]) ``` **Diagram sources** -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) Usage examples: - Setup wizard triggers a “setup_run” audit entry after successfully creating slider options for a product. - Administrative actions across the extension can call the service to maintain a consistent audit trail. **Section sources** -- [AuditLogService.php:15-81](file://Services/AuditLogService.php#L15-L81) -- [AuditsExtensionActions.php:10-32](file://Services/Concerns/AuditsExtensionActions.php#L10-L32) -- [AuditLogPage.php:31-80](file://Admin/Pages/AuditLogPage.php#L31-L80) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [AuditLogService.php:15-81](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L81) +- [AuditsExtensionActions.php:10-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L32) +- [AuditLogPage.php:31-80](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L80) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) ### ConfigOptionSetupService Purpose: @@ -203,7 +206,7 @@ class ConfigOptionSetupService { ``` **Diagram sources** -- [ConfigOptionSetupService.php:44-258](file://Services/ConfigOptionSetupService.php#L44-L258) +- [ConfigOptionSetupService.php:44-258](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L258) Example workflow: - Admin submits slider configuration for a product. @@ -212,9 +215,9 @@ Example workflow: - On success, an audit entry records which sliders were configured and how many. **Section sources** -- [ConfigOptionSetupService.php:44-171](file://Services/ConfigOptionSetupService.php#L44-L171) -- [ConfigOptionSetupService.php:173-258](file://Services/ConfigOptionSetupService.php#L173-L258) -- [AuditsExtensionActions.php:10-32](file://Services/Concerns/AuditsExtensionActions.php#L10-L32) +- [ConfigOptionSetupService.php:44-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L171) +- [ConfigOptionSetupService.php:173-258](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L173-L258) +- [AuditsExtensionActions.php:10-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L32) ### SliderConfigReaderService Purpose: @@ -245,15 +248,15 @@ Controller-->>Client : JSON response ``` **Diagram sources** -- [SliderConfigReaderService.php:14-66](file://Services/SliderConfigReaderService.php#L14-L66) -- [PricingController.php:127-145](file://Http/Controllers/Api/PricingController.php#L127-L145) +- [SliderConfigReaderService.php:14-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L66) +- [PricingController.php:127-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L127-L145) Important note: - Price calculation is delegated to Paymenter core methods (Plan::dynamicSliderBasePrice and ConfigOption::calculateDynamicPriceDelta). This service only provides configuration metadata. **Section sources** -- [SliderConfigReaderService.php:14-66](file://Services/SliderConfigReaderService.php#L14-L66) -- [PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) +- [SliderConfigReaderService.php:14-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L66) +- [PricingController.php:24-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L145) ## Dependency Analysis - ConfigOptionSetupService depends on Paymenter’s ConfigOption model and validation rules to persist slider metadata. It also uses the AuditsExtensionActions trait to emit audit events. @@ -275,20 +278,20 @@ AdminUI["AuditLogPage"] --> DB ``` **Diagram sources** -- [ConfigOptionSetupService.php:44-171](file://Services/ConfigOptionSetupService.php#L44-L171) -- [AuditsExtensionActions.php:10-32](file://Services/Concerns/AuditsExtensionActions.php#L10-L32) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) -- [SliderConfigReaderService.php:14-66](file://Services/SliderConfigReaderService.php#L14-L66) -- [PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) -- [AuditLogPage.php:31-80](file://Admin/Pages/AuditLogPage.php#L31-L80) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [ConfigOptionSetupService.php:44-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L171) +- [AuditsExtensionActions.php:10-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L32) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) +- [SliderConfigReaderService.php:14-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L66) +- [PricingController.php:24-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L145) +- [AuditLogPage.php:31-80](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L80) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) **Section sources** -- [ConfigOptionSetupService.php:44-258](file://Services/ConfigOptionSetupService.php#L44-L258) -- [SliderConfigReaderService.php:14-66](file://Services/SliderConfigReaderService.php#L14-L66) -- [PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) -- [AuditLogService.php:15-81](file://Services/AuditLogService.php#L15-L81) -- [AuditLogPage.php:31-80](file://Admin/Pages/AuditLogPage.php#L31-L80) +- [ConfigOptionSetupService.php:44-258](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L258) +- [SliderConfigReaderService.php:14-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L66) +- [PricingController.php:24-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L145) +- [AuditLogService.php:15-81](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L81) +- [AuditLogPage.php:31-80](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L80) ## Performance Considerations - Audit logging uses direct table inserts with minimal overhead and indexed columns for common queries (entity_type/entity_id, user_id, created_at, action). @@ -309,10 +312,10 @@ Operational checks: - Use the Admin Audit Log page to filter by action, entity type, and date range to investigate changes. **Section sources** -- [AuditsExtensionActions.php:10-32](file://Services/Concerns/AuditsExtensionActions.php#L10-L32) -- [AuditLogPage.php:31-80](file://Admin/Pages/AuditLogPage.php#L31-L80) -- [ConfigOptionSetupService.php:117-171](file://Services/ConfigOptionSetupService.php#L117-L171) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [AuditsExtensionActions.php:10-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L32) +- [AuditLogPage.php:31-80](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L80) +- [ConfigOptionSetupService.php:117-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L117-L171) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) ## Conclusion These supporting services provide essential auxiliary functionality: diff --git a/.qoder/repowiki/en/content/Configuration.md b/.qoder/repowiki/en/content/Configuration.md index abc324c..cea391f 100644 --- a/.qoder/repowiki/en/content/Configuration.md +++ b/.qoder/repowiki/en/content/Configuration.md @@ -1,16 +1,31 @@ # Configuration +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + +## Current Configuration Contract + +The extension settings contain the canonical Pterodactyl URL, encrypted +application API key, exclusive-provisioning confirmation, quote rate-limit +controls, and alert/scheduler settings. Product resource definitions live in +native Paymenter config options. Physical CPU capacity and overcommit behavior +live in per-node `NodeCapacityPolicy` records rather than in panel payloads or +global slider defaults. + +Never place the API key in a URL, log message, rate-limit key, or customer +response. + + **Referenced Files in This Document** -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [SetupWizard.php](file://Admin/Pages/SetupWizard.php) -- [ConfigOptionSetupService.php](file://Services/ConfigOptionSetupService.php) -- [SliderConfigReaderService.php](file://Services/SliderConfigReaderService.php) -- [AlertConfig.php](file://Models/AlertConfig.php) -- [2025_01_01_000004_create_ptero_alert_configs_table.php](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) -- [StoreReservationRequest.php](file://Http/Requests/StoreReservationRequest.php) -- [CartItemCreatedListener.php](file://Listeners/CartItemCreatedListener.php) -- [AlertService.php](file://Services/AlertService.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [SetupWizard.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php) +- [ConfigOptionSetupService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php) +- [SliderConfigReaderService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php) +- [AlertConfig.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php) +- [2025_01_01_000004_create_ptero_alert_configs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) +- [StoreReservationRequest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php) +- [CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php) +- [AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) ## Table of Contents @@ -58,21 +73,21 @@ K["ResourceCalculationService"] --> L["Pterodactyl Panel API"] ``` **Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [SetupWizard.php:80-409](file://Admin/Pages/SetupWizard.php#L80-L409) -- [ConfigOptionSetupService.php:44-206](file://Services/ConfigOptionSetupService.php#L44-L206) -- [SliderConfigReaderService.php:14-66](file://Services/SliderConfigReaderService.php#L14-L66) -- [StoreReservationRequest.php:51-138](file://Http/Requests/StoreReservationRequest.php#L51-L138) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) -- [AlertConfig.php:8-55](file://Models/AlertConfig.php#L8-L55) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [SetupWizard.php:80-409](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L80-L409) +- [ConfigOptionSetupService.php:44-206](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L206) +- [SliderConfigReaderService.php:14-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L66) +- [StoreReservationRequest.php:51-138](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L51-L138) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) +- [AlertConfig.php:8-55](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L55) **Section sources** -- [DynamicPterodactyl.php:45-75](file://DynamicPterodactyl.php#L45-L75) -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [SetupWizard.php:50-78](file://Admin/Pages/SetupWizard.php#L50-L78) -- [ConfigOptionSetupService.php:14-42](file://Services/ConfigOptionSetupService.php#L14-L42) -- [AlertConfig.php:12-34](file://Models/AlertConfig.php#L12-L34) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [DynamicPterodactyl.php:45-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L45-L75) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [SetupWizard.php:50-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L50-L78) +- [ConfigOptionSetupService.php:14-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L14-L42) +- [AlertConfig.php:12-34](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L12-L34) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) ## Core Components - Extension configuration fields: Pterodactyl URL, API key, reservation TTL @@ -87,11 +102,11 @@ Key behaviors: - Pricing is defined by Paymenter’s dynamic_slider pricing engine using metadata produced by the setup service **Section sources** -- [DynamicPterodactyl.php:48-75](file://DynamicPterodactyl.php#L48-L75) -- [SetupWizard.php:80-409](file://Admin/Pages/SetupWizard.php#L80-L409) -- [SliderConfigReaderService.php:14-66](file://Services/SliderConfigReaderService.php#L14-L66) -- [StoreReservationRequest.php:51-138](file://Http/Requests/StoreReservationRequest.php#L51-L138) -- [AlertConfig.php:12-34](file://Models/AlertConfig.php#L12-L34) +- [DynamicPterodactyl.php:48-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L48-L75) +- [SetupWizard.php:80-409](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L80-L409) +- [SliderConfigReaderService.php:14-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L66) +- [StoreReservationRequest.php:51-138](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L51-L138) +- [AlertConfig.php:12-34](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L12-L34) ## Architecture Overview The extension wires together configuration creation, request-time validation, and alerting: @@ -120,12 +135,12 @@ Alert-->>Admin : Send notifications on breach ``` **Diagram sources** -- [SetupWizard.php:429-488](file://Admin/Pages/SetupWizard.php#L429-L488) -- [ConfigOptionSetupService.php:44-206](file://Services/ConfigOptionSetupService.php#L44-L206) -- [SliderConfigReaderService.php:14-66](file://Services/SliderConfigReaderService.php#L14-L66) -- [StoreReservationRequest.php:51-138](file://Http/Requests/StoreReservationRequest.php#L51-L138) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) -- [AlertConfig.php:12-34](file://Models/AlertConfig.php#L12-L34) +- [SetupWizard.php:429-488](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L429-L488) +- [ConfigOptionSetupService.php:44-206](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L206) +- [SliderConfigReaderService.php:14-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L66) +- [StoreReservationRequest.php:51-138](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L51-L138) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) +- [AlertConfig.php:12-34](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L12-L34) ## Detailed Component Analysis @@ -137,7 +152,7 @@ Alert-->>Admin : Send notifications on breach These are managed via the extension’s configuration method and used by services that interact with Pterodactyl and manage reservations. **Section sources** -- [DynamicPterodactyl.php:48-75](file://DynamicPterodactyl.php#L48-L75) +- [DynamicPterodactyl.php:48-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L48-L75) ### Dynamic Slider Options: Creation and Metadata The setup wizard creates dynamic_slider options per product for memory, CPU, and disk. For each resource: @@ -152,9 +167,9 @@ Metadata written into ConfigOptions includes: Validation of pricing metadata uses Paymenter’s rule before saving. **Section sources** -- [SetupWizard.php:80-409](file://Admin/Pages/SetupWizard.php#L80-L409) -- [ConfigOptionSetupService.php:44-171](file://Services/ConfigOptionSetupService.php#L44-L171) -- [ConfigOptionSetupService.php:173-206](file://Services/ConfigOptionSetupService.php#L173-L206) +- [SetupWizard.php:80-409](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L80-L409) +- [ConfigOptionSetupService.php:44-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L171) +- [ConfigOptionSetupService.php:173-206](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L173-L206) ### Slider Configuration Reader Reads dynamic_slider options for a product and returns slider definitions suitable for frontend/API consumption: @@ -162,7 +177,7 @@ Reads dynamic_slider options for a product and returns slider definitions suitab - Handles both array and JSON-encoded metadata **Section sources** -- [SliderConfigReaderService.php:14-66](file://Services/SliderConfigReaderService.php#L14-L66) +- [SliderConfigReaderService.php:14-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L66) ### Request Validation: Slider Ranges and Allowed Locations When creating a reservation: @@ -174,7 +189,7 @@ When creating a reservation: Errors are added to the validator when constraints fail. **Section sources** -- [StoreReservationRequest.php:51-138](file://Http/Requests/StoreReservationRequest.php#L51-L138) +- [StoreReservationRequest.php:51-138](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L51-L138) ### Location-Based Restrictions - The setup wizard can create a “Location” select option with child options for each chosen Pterodactyl location @@ -182,10 +197,10 @@ Errors are added to the validator when constraints fail. - During cart processing, the listener resolves the actual Pterodactyl location ID from the selected child option **Section sources** -- [SetupWizard.php:391-404](file://Admin/Pages/SetupWizard.php#L391-L404) -- [ConfigOptionSetupService.php:173-206](file://Services/ConfigOptionSetupService.php#L173-L206) -- [StoreReservationRequest.php:60-64](file://Http/Requests/StoreReservationRequest.php#L60-L64) -- [CartItemCreatedListener.php:137-159](file://Listeners/CartItemCreatedListener.php#L137-L159) +- [SetupWizard.php:391-404](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L391-L404) +- [ConfigOptionSetupService.php:173-206](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L173-L206) +- [StoreReservationRequest.php:60-64](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L60-L64) +- [CartItemCreatedListener.php:137-159](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L137-L159) ### Alert Thresholds and Notifications Alerts are configured per location or globally: @@ -197,9 +212,9 @@ Alerts are configured per location or globally: The alert service evaluates utilization and sends notifications when thresholds are exceeded. **Section sources** -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) -- [AlertConfig.php:12-34](file://Models/AlertConfig.php#L12-L34) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [AlertConfig.php:12-34](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L12-L34) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) ### Pricing Rules via Paymenter’s Native Engine - Pricing models supported: linear, tiered, base_addon @@ -211,8 +226,8 @@ The alert service evaluates utilization and sends notifications when thresholds The setup service builds pricing metadata and validates it using Paymenter’s rule. Actual price calculation is performed by Paymenter core using Plan and ConfigOption methods. **Section sources** -- [ConfigOptionSetupService.php:117-171](file://Services/ConfigOptionSetupService.php#L117-L171) -- [SetupWizard.php:113-389](file://Admin/Pages/SetupWizard.php#L113-L389) +- [ConfigOptionSetupService.php:117-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L117-L171) +- [SetupWizard.php:113-389](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L113-L389) ### Environment Variables and File-Based Settings - Each dynamic_slider option defines an environment variable name (e.g., MEMORY, CPU, DISK, LOCATION) used by Paymenter to resolve values at runtime @@ -221,8 +236,8 @@ The setup service builds pricing metadata and validates it using Paymenter’s r Note: The extension does not define its own environment variables beyond those tied to slider options. **Section sources** -- [ConfigOptionSetupService.php:96-112](file://Services/ConfigOptionSetupService.php#L96-L112) -- [ConfigOptionSetupService.php:173-206](file://Services/ConfigOptionSetupService.php#L173-L206) +- [ConfigOptionSetupService.php:96-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L96-L112) +- [ConfigOptionSetupService.php:173-206](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L173-L206) ### Runtime Configuration Changes - Slider and pricing metadata are read dynamically from ConfigOptions at request time @@ -230,8 +245,8 @@ Note: The extension does not define its own environment variables beyond those t - No static file-based configuration is used for slider/alert settings **Section sources** -- [SliderConfigReaderService.php:14-66](file://Services/SliderConfigReaderService.php#L14-L66) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) +- [SliderConfigReaderService.php:14-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L66) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) ## Dependency Analysis Configuration flows depend on: @@ -252,18 +267,18 @@ Alerts["AlertService"] --> AConf["AlertConfig"] ``` **Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [SetupWizard.php:429-488](file://Admin/Pages/SetupWizard.php#L429-L488) -- [ConfigOptionSetupService.php:44-206](file://Services/ConfigOptionSetupService.php#L44-L206) -- [StoreReservationRequest.php:51-138](file://Http/Requests/StoreReservationRequest.php#L51-L138) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) -- [AlertConfig.php:12-34](file://Models/AlertConfig.php#L12-L34) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [SetupWizard.php:429-488](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L429-L488) +- [ConfigOptionSetupService.php:44-206](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L206) +- [StoreReservationRequest.php:51-138](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L51-L138) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) +- [AlertConfig.php:12-34](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L12-L34) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [ConfigOptionSetupService.php:44-206](file://Services/ConfigOptionSetupService.php#L44-L206) -- [StoreReservationRequest.php:51-138](file://Http/Requests/StoreReservationRequest.php#L51-L138) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [ConfigOptionSetupService.php:44-206](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L206) +- [StoreReservationRequest.php:51-138](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L51-L138) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) ## Performance Considerations - Pterodactyl API responses are not cached; real-time availability is intentional @@ -284,9 +299,9 @@ Common issues and resolutions: Use the admin setup wizard to re-run configuration updates; warnings will appear if existing slider options are overwritten. **Section sources** -- [StoreReservationRequest.php:51-138](file://Http/Requests/StoreReservationRequest.php#L51-L138) -- [SetupWizard.php:411-488](file://Admin/Pages/SetupWizard.php#L411-L488) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) +- [StoreReservationRequest.php:51-138](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L51-L138) +- [SetupWizard.php:411-488](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L411-L488) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) ## Conclusion Configure the Dynamic Pterodactyl extension by: @@ -297,4 +312,4 @@ Configure the Dynamic Pterodactyl extension by: - Relying on Paymenter’s native pricing engine for price calculations - Validating runtime inputs against configured sliders and locations -This approach ensures consistent, auditable, and maintainable configuration across products while preserving real-time availability and robust reservation handling. \ No newline at end of file +This approach ensures consistent, auditable, and maintainable configuration across products while preserving real-time availability and robust reservation handling. diff --git a/.qoder/repowiki/en/content/Core Services/ConfigOptionSetupService.md b/.qoder/repowiki/en/content/Core Services/ConfigOptionSetupService.md index 0505482..8edf6ae 100644 --- a/.qoder/repowiki/en/content/Core Services/ConfigOptionSetupService.md +++ b/.qoder/repowiki/en/content/Core Services/ConfigOptionSetupService.md @@ -1,17 +1,20 @@ # ConfigOptionSetupService +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [ConfigOptionSetupService.php](file://Services/ConfigOptionSetupService.php) -- [SliderConfigReaderService.php](file://Services/SliderConfigReaderService.php) -- [AuditsExtensionActions.php](file://Services/Concerns/AuditsExtensionActions.php) -- [PricingController.php](file://Http/Controllers/Api/PricingController.php) -- [StoreReservationRequest.php](file://Http/Requests/StoreReservationRequest.php) -- [2025_01_01_000002_create_ptero_pricing_configs_table.php](file://database/migrations/2025_01_01_000002_create_ptero_pricing_configs_table.php) -- [2025_01_01_000005_drop_ptero_pricing_configs_table.php](file://database/migrations/2025_01_01_000005_drop_ptero_pricing_configs_table.php) -- [ConfigOptionSetupServiceTest.php](file://tests/Unit/ConfigOptionSetupServiceTest.php) -- [SetupWizardValidationTest.php](file://tests/Feature/SetupWizardValidationTest.php) -- [LaravelTestCase.php](file://tests/LaravelTestCase.php) +- [ConfigOptionSetupService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php) +- [SliderConfigReaderService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php) +- [AuditsExtensionActions.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php) +- [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) +- [StoreReservationRequest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php) +- [2025_01_01_000002_create_ptero_pricing_configs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000002_create_ptero_pricing_configs_table.php) +- [2025_01_01_000005_drop_ptero_pricing_configs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000005_drop_ptero_pricing_configs_table.php) +- [ConfigOptionSetupServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ConfigOptionSetupServiceTest.php) +- [SetupWizardValidationTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/SetupWizardValidationTest.php) +- [LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) ## Table of Contents @@ -44,14 +47,14 @@ H["StoreReservationRequest"] --> C ``` **Diagram sources** -- [ConfigOptionSetupService.php:44-77](file://Services/ConfigOptionSetupService.php#L44-L77) -- [SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) -- [PricingController.php:38-76](file://Http/Controllers/Api/PricingController.php#L38-L76) -- [StoreReservationRequest.php:75-140](file://Http/Requests/StoreReservationRequest.php#L75-L140) +- [ConfigOptionSetupService.php:44-77](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L77) +- [SliderConfigReaderService.php:14-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L53) +- [PricingController.php:38-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L38-L76) +- [StoreReservationRequest.php:75-140](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L75-L140) **Section sources** -- [ConfigOptionSetupService.php:1-259](file://Services/ConfigOptionSetupService.php#L1-L259) -- [SliderConfigReaderService.php:1-68](file://Services/SliderConfigReaderService.php#L1-L68) +- [ConfigOptionSetupService.php:1-259](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L1-L259) +- [SliderConfigReaderService.php:1-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L1-L68) ## Core Components - ConfigOptionSetupService: Creates/updates dynamic_slider ConfigOptions for memory, CPU, disk, and optionally Location; validates pricing metadata; audits setup runs. @@ -66,14 +69,14 @@ Key responsibilities: - Provide helpers to detect existing slider options and count products with sliders. **Section sources** -- [ConfigOptionSetupService.php:14-42](file://Services/ConfigOptionSetupService.php#L14-L42) -- [ConfigOptionSetupService.php:44-77](file://Services/ConfigOptionSetupService.php#L44-L77) -- [ConfigOptionSetupService.php:79-146](file://Services/ConfigOptionSetupService.php#L79-L146) -- [ConfigOptionSetupService.php:148-171](file://Services/ConfigOptionSetupService.php#L148-L171) -- [ConfigOptionSetupService.php:173-206](file://Services/ConfigOptionSetupService.php#L173-L206) -- [ConfigOptionSetupService.php:208-258](file://Services/ConfigOptionSetupService.php#L208-L258) -- [SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) -- [AuditsExtensionActions.php:10-32](file://Services/Concerns/AuditsExtensionActions.php#L10-L32) +- [ConfigOptionSetupService.php:14-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L14-L42) +- [ConfigOptionSetupService.php:44-77](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L77) +- [ConfigOptionSetupService.php:79-146](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L79-L146) +- [ConfigOptionSetupService.php:148-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L148-L171) +- [ConfigOptionSetupService.php:173-206](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L173-L206) +- [ConfigOptionSetupService.php:208-258](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L208-L258) +- [SliderConfigReaderService.php:14-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L53) +- [AuditsExtensionActions.php:10-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L32) ## Architecture Overview The service orchestrates slider creation within a single transaction. For each enabled resource type, it either updates an existing dynamic_slider option or creates a new one, attaching it to the product. Pricing metadata is validated before persisting. If locations are provided, a Location select option and its child options are created. After success, an audit entry is recorded. @@ -105,10 +108,10 @@ Svc-->>Admin : created options map ``` **Diagram sources** -- [ConfigOptionSetupService.php:44-77](file://Services/ConfigOptionSetupService.php#L44-L77) -- [ConfigOptionSetupService.php:79-146](file://Services/ConfigOptionSetupService.php#L79-L146) -- [ConfigOptionSetupService.php:173-206](file://Services/ConfigOptionSetupService.php#L173-L206) -- [AuditsExtensionActions.php:10-32](file://Services/Concerns/AuditsExtensionActions.php#L10-L32) +- [ConfigOptionSetupService.php:44-77](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L77) +- [ConfigOptionSetupService.php:79-146](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L79-L146) +- [ConfigOptionSetupService.php:173-206](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L173-L206) +- [AuditsExtensionActions.php:10-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L32) ## Detailed Component Analysis @@ -131,10 +134,10 @@ Output: - Map of resource types to created/updated ConfigOption instances, plus location if created. **Section sources** -- [ConfigOptionSetupService.php:44-77](file://Services/ConfigOptionSetupService.php#L44-L77) -- [ConfigOptionSetupService.php:79-146](file://Services/ConfigOptionSetupService.php#L79-L146) -- [ConfigOptionSetupService.php:148-171](file://Services/ConfigOptionSetupService.php#L148-L171) -- [ConfigOptionSetupService.php:173-206](file://Services/ConfigOptionSetupService.php#L173-L206) +- [ConfigOptionSetupService.php:44-77](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L77) +- [ConfigOptionSetupService.php:79-146](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L79-L146) +- [ConfigOptionSetupService.php:148-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L148-L171) +- [ConfigOptionSetupService.php:173-206](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L173-L206) ### Validating configuration constraints - Pricing metadata validation is delegated to Paymenter’s DynamicSliderPricingRule during buildResourceMetadata. @@ -149,8 +152,8 @@ Validation rules enforced at setup time include: These rules mirror those used elsewhere in the system to ensure consistency between setup and runtime. **Section sources** -- [ConfigOptionSetupService.php:117-146](file://Services/ConfigOptionSetupService.php#L117-L146) -- [07-PRICING-MODELS.md:309-319](file://07-PRICING-MODELS.md#L309-L319) +- [ConfigOptionSetupService.php:117-146](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L117-L146) +- [07-PRICING-MODELS.md:309-319](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/07-PRICING-MODELS.md#L309-L319) ### Integrating with Paymenter’s pricing engine - The service does not calculate prices. It stores metadata consumed by Paymenter core pricing methods: @@ -172,15 +175,15 @@ Submit --> End(["Checkout/Reservation"]) ``` **Diagram sources** -- [ConfigOptionSetupService.php:117-146](file://Services/ConfigOptionSetupService.php#L117-L146) -- [SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) -- [PricingController.php:38-76](file://Http/Controllers/Api/PricingController.php#L38-L76) -- [StoreReservationRequest.php:75-140](file://Http/Requests/StoreReservationRequest.php#L75-L140) +- [ConfigOptionSetupService.php:117-146](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L117-L146) +- [SliderConfigReaderService.php:14-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L53) +- [PricingController.php:38-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L38-L76) +- [StoreReservationRequest.php:75-140](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L75-L140) **Section sources** -- [SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) -- [PricingController.php:38-76](file://Http/Controllers/Api/PricingController.php#L38-L76) -- [StoreReservationRequest.php:75-140](file://Http/Requests/StoreReservationRequest.php#L75-L140) +- [SliderConfigReaderService.php:14-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L53) +- [PricingController.php:38-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L38-L76) +- [StoreReservationRequest.php:75-140](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L75-L140) ### Relationship between slider configurations and product definitions - Each dynamic_slider ConfigOption is linked to a product via the pivot table. @@ -189,9 +192,9 @@ Submit --> End(["Checkout/Reservation"]) - Location options are hierarchical: a parent “Location” option with child options representing available locations. **Section sources** -- [ConfigOptionSetupService.php:79-115](file://Services/ConfigOptionSetupService.php#L79-L115) -- [ConfigOptionSetupService.php:173-206](file://Services/ConfigOptionSetupService.php#L173-L206) -- [ConfigOptionSetupService.php:235-248](file://Services/ConfigOptionSetupService.php#L235-L248) +- [ConfigOptionSetupService.php:79-115](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L79-L115) +- [ConfigOptionSetupService.php:173-206](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L173-L206) +- [ConfigOptionSetupService.php:235-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L235-L248) ### Migration procedures for updating existing slider setups - Historical ptero_pricing_configs table was removed; slider configuration now lives in ConfigOption metadata. @@ -205,9 +208,9 @@ Migration notes: - The drop migration removes the legacy table and documents data loss on rollback; reconfiguration should be done via the Setup Wizard after rollback. **Section sources** -- [2025_01_01_000005_drop_ptero_pricing_configs_table.php:12-27](file://database/migrations/2025_01_01_000005_drop_ptero_pricing_configs_table.php#L12-L27) -- [ConfigOptionSetupService.php:208-233](file://Services/ConfigOptionSetupService.php#L208-L233) -- [ConfigOptionSetupService.php:235-248](file://Services/ConfigOptionSetupService.php#L235-L248) +- [2025_01_01_000005_drop_ptero_pricing_configs_table.php:12-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000005_drop_ptero_pricing_configs_table.php#L12-L27) +- [ConfigOptionSetupService.php:208-233](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L208-L233) +- [ConfigOptionSetupService.php:235-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L235-L248) ### Common configuration patterns - Linear pricing: set base_price and per-resource rates (e.g., memory_rate, cpu_rate, disk_rate). @@ -221,10 +224,10 @@ Examples validated by tests: - Audit logging of setup runs with correct payload. **Section sources** -- [ConfigOptionSetupServiceTest.php:25-51](file://tests/Unit/ConfigOptionSetupServiceTest.php#L25-L51) -- [ConfigOptionSetupServiceTest.php:53-76](file://tests/Unit/ConfigOptionSetupServiceTest.php#L53-L76) -- [ConfigOptionSetupServiceTest.php:78-106](file://tests/Unit/ConfigOptionSetupServiceTest.php#L78-L106) -- [SetupWizardValidationTest.php:75-93](file://tests/Feature/SetupWizardValidationTest.php#L75-L93) +- [ConfigOptionSetupServiceTest.php:25-51](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ConfigOptionSetupServiceTest.php#L25-L51) +- [ConfigOptionSetupServiceTest.php:53-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ConfigOptionSetupServiceTest.php#L53-L76) +- [ConfigOptionSetupServiceTest.php:78-106](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ConfigOptionSetupServiceTest.php#L78-L106) +- [SetupWizardValidationTest.php:75-93](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/SetupWizardValidationTest.php#L75-L93) ### Troubleshooting invalid setups Symptoms and causes: @@ -242,9 +245,9 @@ Recovery: - Inspect audit logs to confirm successful setup runs. **Section sources** -- [ConfigOptionSetupService.php:117-146](file://Services/ConfigOptionSetupService.php#L117-L146) -- [StoreReservationRequest.php:75-140](file://Http/Requests/StoreReservationRequest.php#L75-L140) -- [ConfigOptionSetupServiceTest.php:25-51](file://tests/Unit/ConfigOptionSetupServiceTest.php#L25-L51) +- [ConfigOptionSetupService.php:117-146](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L117-L146) +- [StoreReservationRequest.php:75-140](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L75-L140) +- [ConfigOptionSetupServiceTest.php:25-51](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ConfigOptionSetupServiceTest.php#L25-L51) ## Dependency Analysis - External dependencies: @@ -280,14 +283,14 @@ ConfigOptionSetupService --> SliderConfigReaderService : "conceptual read path" ``` **Diagram sources** -- [ConfigOptionSetupService.php:10-258](file://Services/ConfigOptionSetupService.php#L10-L258) -- [SliderConfigReaderService.php:7-66](file://Services/SliderConfigReaderService.php#L7-L66) -- [AuditsExtensionActions.php:8-32](file://Services/Concerns/AuditsExtensionActions.php#L8-L32) +- [ConfigOptionSetupService.php:10-258](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L10-L258) +- [SliderConfigReaderService.php:7-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L7-L66) +- [AuditsExtensionActions.php:8-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L8-L32) **Section sources** -- [ConfigOptionSetupService.php:10-258](file://Services/ConfigOptionSetupService.php#L10-L258) -- [SliderConfigReaderService.php:7-66](file://Services/SliderConfigReaderService.php#L7-L66) -- [AuditsExtensionActions.php:8-32](file://Services/Concerns/AuditsExtensionActions.php#L8-L32) +- [ConfigOptionSetupService.php:10-258](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L10-L258) +- [SliderConfigReaderService.php:7-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L7-L66) +- [AuditsExtensionActions.php:8-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L8-L32) ## Performance Considerations - All slider creations/updates occur within a single database transaction to minimize partial writes and simplify rollback. @@ -310,9 +313,9 @@ ConfigOptionSetupService --> SliderConfigReaderService : "conceptual read path" - Confirm audit logs show a successful setup_run action. **Section sources** -- [ConfigOptionSetupService.php:117-146](file://Services/ConfigOptionSetupService.php#L117-L146) -- [StoreReservationRequest.php:75-140](file://Http/Requests/StoreReservationRequest.php#L75-L140) -- [ConfigOptionSetupServiceTest.php:25-51](file://tests/Unit/ConfigOptionSetupServiceTest.php#L25-L51) +- [ConfigOptionSetupService.php:117-146](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L117-L146) +- [StoreReservationRequest.php:75-140](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L75-L140) +- [ConfigOptionSetupServiceTest.php:25-51](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ConfigOptionSetupServiceTest.php#L25-L51) ## Conclusion ConfigOptionSetupService centralizes the creation and validation of dynamic slider options for Paymenter products. It standardizes slider metadata, enforces pricing constraints via core rules, and integrates seamlessly with downstream components that read slider configuration and perform pricing previews and validations. The migration to native ConfigOption metadata simplifies the architecture and improves maintainability. Administrators can safely re-run setup to update configurations while preserving data integrity through transactions and robust validation. @@ -344,7 +347,7 @@ Req-->>Admin : Success or validation errors ``` **Diagram sources** -- [ConfigOptionSetupService.php:44-77](file://Services/ConfigOptionSetupService.php#L44-L77) -- [SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) -- [PricingController.php:38-76](file://Http/Controllers/Api/PricingController.php#L38-L76) -- [StoreReservationRequest.php:75-140](file://Http/Requests/StoreReservationRequest.php#L75-L140) \ No newline at end of file +- [ConfigOptionSetupService.php:44-77](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L77) +- [SliderConfigReaderService.php:14-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L53) +- [PricingController.php:38-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L38-L76) +- [StoreReservationRequest.php:75-140](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L75-L140) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index 81f72ed..eed9d8a 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -1,17 +1,37 @@ # Core Services +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + +## Current Service Map + +- `PterodactylInventoryService` owns strict, paginated application-API reads. +- `ResourceCalculationService` combines live inventory, local commitments, and + `NodeCapacityPolicy` records into capacity snapshots. +- `ResourceQuoteService` produces customer-safe, complete-vector quotes. +- `ProductResourceConfigurationService` resolves native Paymenter config + options; it replaces the retired `SliderConfigReaderService` role. +- `ReservationService` owns cart and paid-service commitments. +- `UpgradeReservationService` owns quote, payment, provisioning, expiry, and + reconciliation state for service upgrades. +- `AllocationSelectionService`, `NodeSelectionService`, `AlertService`, + `SchedulerHealthService`, and the audit/configuration services provide the + supporting policies and operator visibility. + +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/02-SERVICES.md) + + **Referenced Files in This Document** -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [NodeSelectionService.php](file://Services/NodeSelectionService.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [AlertService.php](file://Services/AlertService.php) -- [ConfigOptionSetupService.php](file://Services/ConfigOptionSetupService.php) -- [SliderConfigReaderService.php](file://Services/SliderConfigReaderService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [AlertConfig.php](file://Models/AlertConfig.php) -- [AuditsExtensionActions.php](file://Services/Concerns/AuditsExtensionActions.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [NodeSelectionService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) +- [ConfigOptionSetupService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php) +- [SliderConfigReaderService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [AlertConfig.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php) +- [AuditsExtensionActions.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php) ## Table of Contents @@ -64,10 +84,10 @@ J --> G ``` **Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) ## Core Components - ResourceCalculationService: Real-time availability and cluster snapshot builder using Pterodactyl API calls and pending reservations. @@ -78,12 +98,12 @@ J --> G - SliderConfigReaderService: Reads slider metadata for frontend/API consumption. **Section sources** -- [ResourceCalculationService.php:23-222](file://Services/ResourceCalculationService.php#L23-L222) -- [NodeSelectionService.php:14-86](file://Services/NodeSelectionService.php#L14-L86) -- [ReservationService.php:37-405](file://Services/ReservationService.php#L37-L405) -- [AlertService.php:30-248](file://Services/AlertService.php#L30-L248) -- [ConfigOptionSetupService.php:44-258](file://Services/ConfigOptionSetupService.php#L44-L258) -- [SliderConfigReaderService.php:9-66](file://Services/SliderConfigReaderService.php#L9-L66) +- [ResourceCalculationService.php:23-222](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L23-L222) +- [NodeSelectionService.php:14-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L14-L86) +- [ReservationService.php:37-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L37-L405) +- [AlertService.php:30-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L30-L248) +- [ConfigOptionSetupService.php:44-258](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L258) +- [SliderConfigReaderService.php:9-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L9-L66) ## Architecture Overview The services form a layered pipeline: @@ -118,9 +138,9 @@ end ``` **Diagram sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) ## Detailed Component Analysis @@ -161,10 +181,10 @@ Integration points: - Reads extension config for API URL/key. **Section sources** -- [ResourceCalculationService.php:23-222](file://Services/ResourceCalculationService.php#L23-L222) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) -- [ResourceCalculationService.php:302-384](file://Services/ResourceCalculationService.php#L302-L384) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:23-222](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L23-L222) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) +- [ResourceCalculationService.php:302-384](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L302-L384) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) ### NodeSelectionService Responsibilities: @@ -191,7 +211,7 @@ Integration points: - Called by ReservationService during reservation creation. **Section sources** -- [NodeSelectionService.php:14-86](file://Services/NodeSelectionService.php#L14-L86) +- [NodeSelectionService.php:14-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L14-L86) ### ReservationService Responsibilities: @@ -236,9 +256,9 @@ Integration points: - Schedules cleanup via DynamicPterodactyl boot. **Section sources** -- [ReservationService.php:37-405](file://Services/ReservationService.php#L37-L405) -- [AuditsExtensionActions.php:8-33](file://Services/Concerns/AuditsExtensionActions.php#L8-L33) -- [DynamicPterodactyl.php:116-121](file://DynamicPterodactyl.php#L116-L121) +- [ReservationService.php:37-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L37-L405) +- [AuditsExtensionActions.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L8-L33) +- [DynamicPterodactyl.php:116-121](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L116-L121) ### AlertService Responsibilities: @@ -268,8 +288,8 @@ Integration points: - Uses Notification classes and AlertDeliveryLog model. **Section sources** -- [AlertService.php:30-248](file://Services/AlertService.php#L30-L248) -- [AlertService.php:301-361](file://Services/AlertService.php#L301-L361) +- [AlertService.php:30-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L30-L248) +- [AlertService.php:301-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L301-L361) ### ConfigOptionSetupService Responsibilities: @@ -294,7 +314,7 @@ Integration points: - Audits setup runs. **Section sources** -- [ConfigOptionSetupService.php:44-258](file://Services/ConfigOptionSetupService.php#L44-L258) +- [ConfigOptionSetupService.php:44-258](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L258) ### SliderConfigReaderService Responsibilities: @@ -311,7 +331,7 @@ Integration points: - Reads ConfigOption entries created by ConfigOptionSetupService. **Section sources** -- [SliderConfigReaderService.php:9-66](file://Services/SliderConfigReaderService.php#L9-L66) +- [SliderConfigReaderService.php:9-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L9-L66) ## Dependency Analysis Service dependencies and relationships: @@ -337,10 +357,10 @@ SliderConfigReaderService --> ResourceReservation : "not directly" ``` **Diagram sources** -- [NodeSelectionService.php:7-12](file://Services/NodeSelectionService.php#L7-L12) -- [ReservationService.php:20-35](file://Services/ReservationService.php#L20-L35) -- [AlertService.php:23-28](file://Services/AlertService.php#L23-L28) -- [AuditsExtensionActions.php:8-33](file://Services/Concerns/AuditsExtensionActions.php#L8-L33) +- [NodeSelectionService.php:7-12](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L7-L12) +- [ReservationService.php:20-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L20-L35) +- [AlertService.php:23-28](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L23-L28) +- [AuditsExtensionActions.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L8-L33) Coupling and cohesion: - ResourceCalculationService is a foundational dependency with high cohesion around availability computation. @@ -358,8 +378,8 @@ External integrations: - Laravel scheduling and event system. **Section sources** -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) ## Performance Considerations - Real-time API usage: ResourceCalculationService avoids caching to ensure accuracy; batch requests and pagination minimize round-trips. @@ -389,10 +409,10 @@ Common issues and resolutions: - Action: Validate admin recipients and webhook URLs; check cooldowns; inspect logs for channel errors. **Section sources** -- [ResourceCalculationService.php:157-195](file://Services/ResourceCalculationService.php#L157-L195) -- [ResourceCalculationService.php:410-424](file://Services/ResourceCalculationService.php#L410-L424) -- [ReservationService.php:125-141](file://Services/ReservationService.php#L125-L141) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) +- [ResourceCalculationService.php:157-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L157-L195) +- [ResourceCalculationService.php:410-424](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L410-L424) +- [ReservationService.php:125-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L125-L141) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) ## Conclusion The Dynamic Pterodactyl extension’s core services provide a robust foundation for real-time availability, intelligent node selection, transactional reservations with TTL, and proactive capacity alerts. Their design emphasizes correctness (locking, idempotency), resilience (retries, degraded modes), and clarity (separation of concerns across services). Integration with Paymenter remains focused on configuration and events, while pricing logic stays within core. @@ -462,7 +482,7 @@ Present --> End(["Done"]) ``` **Diagram sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) #### Capacity Alert Evaluation Flow ```mermaid @@ -483,6 +503,6 @@ NextCfg --> Done(["End"]) ``` **Diagram sources** -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) diff --git a/.qoder/repowiki/en/content/Core Services/NodeSelectionService.md b/.qoder/repowiki/en/content/Core Services/NodeSelectionService.md index 5db14a4..7539716 100644 --- a/.qoder/repowiki/en/content/Core Services/NodeSelectionService.md +++ b/.qoder/repowiki/en/content/Core Services/NodeSelectionService.md @@ -1,13 +1,16 @@ # NodeSelectionService +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [NodeSelectionService.php](file://Services/NodeSelectionService.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) -- [NodeSelectionServiceTest.php](file://tests/Unit/NodeSelectionServiceTest.php) -- [ResourceCalculationServiceTest.php](file://tests/Unit/ResourceCalculationServiceTest.php) +- [NodeSelectionService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) +- [NodeSelectionServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/NodeSelectionServiceTest.php) +- [ResourceCalculationServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php) ## Table of Contents @@ -48,16 +51,16 @@ RCS --> PTERO ``` **Diagram sources** -- [AvailabilityController.php:9-20](file://Http/Controllers/Api/AvailabilityController.php#L9-L20) -- [ReservationService.php:20-35](file://Services/ReservationService.php#L20-L35) -- [NodeSelectionService.php:5-12](file://Services/NodeSelectionService.php#L5-L12) -- [ResourceCalculationService.php:10-21](file://Services/ResourceCalculationService.php#L10-L21) +- [AvailabilityController.php:9-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L9-L20) +- [ReservationService.php:20-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L20-L35) +- [NodeSelectionService.php:5-12](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L5-L12) +- [ResourceCalculationService.php:10-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L10-L21) **Section sources** -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [ReservationService.php:43-124](file://Services/ReservationService.php#L43-L124) -- [NodeSelectionService.php:5-86](file://Services/NodeSelectionService.php#L5-L86) -- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [ReservationService.php:43-124](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L124) +- [NodeSelectionService.php:5-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L5-L86) +- [ResourceCalculationService.php:23-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L23-L67) ## Core Components - NodeSelectionService: Implements best-fit selection using weighted headroom scoring and filters out unsuitable nodes. @@ -72,10 +75,10 @@ Key responsibilities: - AvailabilityController: Present capacity summaries and ensure no sensitive node details are exposed. **Section sources** -- [NodeSelectionService.php:14-86](file://Services/NodeSelectionService.php#L14-L86) -- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) -- [ReservationService.php:43-124](file://Services/ReservationService.php#L43-L124) -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [NodeSelectionService.php:14-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L14-L86) +- [ResourceCalculationService.php:23-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L23-L67) +- [ReservationService.php:43-124](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L124) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) ## Architecture Overview The selection process is a two-phase pipeline: @@ -100,9 +103,9 @@ NSS-->>Caller : best node or null ``` **Diagram sources** -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [ResourceCalculationService.php:23-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L23-L67) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) ## Detailed Component Analysis @@ -158,8 +161,8 @@ Examples validated by tests: - Weighted scoring prefers memory headroom due to its higher weight. **Section sources** -- [NodeSelectionService.php:14-86](file://Services/NodeSelectionService.php#L14-L86) -- [NodeSelectionServiceTest.php:32-351](file://tests/Unit/NodeSelectionServiceTest.php#L32-L351) +- [NodeSelectionService.php:14-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L14-L86) +- [NodeSelectionServiceTest.php:32-351](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/NodeSelectionServiceTest.php#L32-L351) ### ResourceCalculationService Responsibilities: @@ -184,10 +187,10 @@ Error handling and resilience: - Server errors (5xx) degrade gracefully in cluster snapshot paths. **Section sources** -- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ResourceCalculationServiceTest.php:53-139](file://tests/Unit/ResourceCalculationServiceTest.php#L53-L139) +- [ResourceCalculationService.php:23-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L23-L67) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationServiceTest.php:53-139](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L53-L139) ### Integration with ReservationService ReservationService orchestrates the reservation lifecycle and depends on NodeSelectionService during creation: @@ -204,7 +207,7 @@ Flow highlights: - Audit actions for traceability. **Section sources** -- [ReservationService.php:43-124](file://Services/ReservationService.php#L43-L124) +- [ReservationService.php:43-124](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L124) ### Integration with AvailabilityController AvailabilityController provides separate customer and administrator surfaces: @@ -215,7 +218,7 @@ Usage of NodeSelectionService: - getMaxAvailable(locationId, locationData) reads per-location maximums from the already fetched snapshot, avoiding a second panel request. **Section sources** -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) ## Dependency Analysis - NodeSelectionService depends on ResourceCalculationService for live availability data. @@ -249,16 +252,16 @@ AvailabilityController --> ResourceCalculationService : "uses" ``` **Diagram sources** -- [NodeSelectionService.php:5-86](file://Services/NodeSelectionService.php#L5-L86) -- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) -- [ReservationService.php:20-35](file://Services/ReservationService.php#L20-L35) -- [AvailabilityController.php:9-20](file://Http/Controllers/Api/AvailabilityController.php#L9-L20) +- [NodeSelectionService.php:5-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L5-L86) +- [ResourceCalculationService.php:23-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L23-L67) +- [ReservationService.php:20-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L20-L35) +- [AvailabilityController.php:9-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L9-L20) **Section sources** -- [NodeSelectionService.php:5-86](file://Services/NodeSelectionService.php#L5-L86) -- [ResourceCalculationService.php:23-67](file://Services/ResourceCalculationService.php#L23-L67) -- [ReservationService.php:20-35](file://Services/ReservationService.php#L20-L35) -- [AvailabilityController.php:9-20](file://Http/Controllers/Api/AvailabilityController.php#L9-L20) +- [NodeSelectionService.php:5-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L5-L86) +- [ResourceCalculationService.php:23-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L23-L67) +- [ReservationService.php:20-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L20-L35) +- [AvailabilityController.php:9-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L9-L20) ## Performance Considerations - Real-time queries: ResourceCalculationService always queries Pterodactyl for current availability; this avoids stale state but incurs network latency. @@ -289,10 +292,10 @@ Operational tips: - Ensure pending reservations are cleaned up to prevent artificial scarcity. **Section sources** -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [ReservationService.php:75-79](file://Services/ReservationService.php#L75-L79) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ResourceCalculationServiceTest.php:53-139](file://tests/Unit/ResourceCalculationServiceTest.php#L53-L139) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [ReservationService.php:75-79](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L75-L79) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationServiceTest.php:53-139](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L53-L139) ## Conclusion NodeSelectionService provides a robust, weighted best-fit algorithm that balances memory, disk, and CPU headroom to select optimal nodes for resource allocation. It integrates tightly with ResourceCalculationService for real-time availability and works within ReservationService’s transactional and idempotent reservation workflow. The design ensures safety through maintenance mode filtering, hard constraint enforcement, and clear error signaling when resources are insufficient. Customer-facing APIs remain safe by exposing only aggregate capacity metrics. diff --git a/.qoder/repowiki/en/content/Core Services/ReservationService.md b/.qoder/repowiki/en/content/Core Services/ReservationService.md index 5013598..91ec4aa 100644 --- a/.qoder/repowiki/en/content/Core Services/ReservationService.md +++ b/.qoder/repowiki/en/content/Core Services/ReservationService.md @@ -1,19 +1,22 @@ # ReservationService +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [ReservationService.php](file://Services/ReservationService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [ReservationController.php](file://Http/Controllers/Api/ReservationController.php) -- [StoreReservationRequest.php](file://Http/Requests/StoreReservationRequest.php) -- [CartItemCreatedListener.php](file://Listeners/CartItemCreatedListener.php) -- [InvoicePaidListener.php](file://Listeners/InvoicePaidListener.php) -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) -- [NodeSelectionService.php](file://Services/NodeSelectionService.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [ResourceReservationPolicy.php](file://Policies/ResourceReservationPolicy.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) +- [StoreReservationRequest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php) +- [CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php) +- [InvoicePaidListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) +- [NodeSelectionService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [ResourceReservationPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php) ## Table of Contents @@ -58,16 +61,16 @@ Policy["ResourceReservationPolicy"] --> RS ``` **Diagram sources** -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [ReservationService.php:43-453](file://Services/ReservationService.php#L43-L453) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [ReservationService.php:43-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L453) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) ## Core Components - ReservationService: Central orchestrator for creating, confirming, cancelling, extending, querying, cleaning up, and reporting on reservations. @@ -79,14 +82,14 @@ Policy["ResourceReservationPolicy"] --> RS - Migrations: Define schema, indexes, and idempotency constraints. **Section sources** -- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ResourceReservationPolicy.php:9-68](file://Policies/ResourceReservationPolicy.php#L9-L68) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:11-20](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L11-L20) +- [ReservationService.php:16-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L453) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ResourceReservationPolicy.php:9-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L68) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:11-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L11-L20) ## Architecture Overview The reservation lifecycle is event-driven and transactional: @@ -120,11 +123,11 @@ RS-->>IPL : true/false ``` **Diagram sources** -- [ReservationController.php:24-60](file://Http/Controllers/Api/ReservationController.php#L24-L60) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [NodeSelectionService.php:22-76](file://Services/NodeSelectionService.php#L22-L76) -- [CartItemCreatedListener.php:47-87](file://Listeners/CartItemCreatedListener.php#L47-L87) -- [InvoicePaidListener.php:36-96](file://Listeners/InvoicePaidListener.php#L36-L96) +- [ReservationController.php:24-60](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L60) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [NodeSelectionService.php:22-76](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L76) +- [CartItemCreatedListener.php:47-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L47-L87) +- [InvoicePaidListener.php:36-96](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L36-L96) ## Detailed Component Analysis @@ -161,14 +164,14 @@ Error handling: - Controller catches exceptions and returns appropriate JSON responses. **Section sources** -- [ReservationService.php:24-35](file://Services/ReservationService.php#L24-L35) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ReservationService.php:250-281](file://Services/ReservationService.php#L250-L281) -- [ReservationService.php:335-382](file://Services/ReservationService.php#L335-L382) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [ReservationService.php:431-452](file://Services/ReservationService.php#L431-L452) +- [ReservationService.php:24-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L24-L35) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ReservationService.php:250-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L250-L281) +- [ReservationService.php:335-382](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L335-L382) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [ReservationService.php:431-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L431-L452) #### Class diagram ```mermaid @@ -199,9 +202,9 @@ ReservationService --> ResourceReservation : "queries/admin list" ``` **Diagram sources** -- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) -- [NodeSelectionService.php:5-86](file://Services/NodeSelectionService.php#L5-L86) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [ReservationService.php:16-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L453) +- [NodeSelectionService.php:5-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L5-L86) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ### Data Model and Constraints - Table stores token, idempotency_key, active computed column, links to cart/service/user, node/location, reserved resources, pricing snapshot, status, notes, and timestamps. @@ -209,8 +212,8 @@ ReservationService --> ResourceReservation : "queries/admin list" - Unique constraint on token; unique constraint on (user_id, active_idempotency_key) ensures one active reservation per idempotency key per user. **Section sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:11-20](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L11-L20) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:11-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L11-L20) ### API Surface and Validation - Create: Accepts product_id, location_id, resource sliders (memory/cpu/disk), optional cart_item_id, and optional idempotency_key header or body field. Validates presence and ranges based on product configuration. @@ -219,8 +222,8 @@ ReservationService --> ResourceReservation : "queries/admin list" - Extend: Validates minutes range; extends TTL and returns updated expiry. **Section sources** -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [StoreReservationRequest.php:38-112](file://Http/Requests/StoreReservationRequest.php#L38-L112) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) ### Event Integrations @@ -228,25 +231,25 @@ ReservationService --> ResourceReservation : "queries/admin list" - Detects products with dynamic_slider options, extracts memory/cpu/disk values and location, then creates a reservation via ReservationService. Stores token and selected node in checkout_config for later use. Errors are logged but do not block cart flow. **Section sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) #### Invoice Paid Listener - For each invoice item referencing a Service, retrieves the reservation token from service properties. Verifies current availability against the reserved snapshot. If available, confirms the reservation; otherwise logs shortfall and notifies via AlertService. Handles state drift where reservation may have been cancelled or expired between verification and confirmation. **Section sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) ### Scheduling and Cleanup - The extension boot registers a scheduler that runs every minute to call cleanupExpired(), marking overdue pending reservations as expired without overlapping runs. A second schedule checks capacity alerts every five minutes. **Section sources** -- [DynamicPterodactyl.php:116-127](file://DynamicPterodactyl.php#L116-L127) +- [DynamicPterodactyl.php:116-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L116-L127) ### Authorization - ResourceReservationPolicy allows admin bypass via Filament panel access. For regular users, view/cancel/extend/confirm require ownership (reservation.user_id matches current user). System callers pass null actor to skip policy checks where appropriate. **Section sources** -- [ResourceReservationPolicy.php:9-68](file://Policies/ResourceReservationPolicy.php#L9-L68) +- [ResourceReservationPolicy.php:9-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L68) ## Dependency Analysis ```mermaid @@ -262,18 +265,18 @@ Sched --> RS ``` **Diagram sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [CartItemCreatedListener.php:47-87](file://Listeners/CartItemCreatedListener.php#L47-L87) -- [InvoicePaidListener.php:36-96](file://Listeners/InvoicePaidListener.php#L36-L96) -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [CartItemCreatedListener.php:47-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L47-L87) +- [InvoicePaidListener.php:36-96](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L36-L96) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [CartItemCreatedListener.php:47-87](file://Listeners/CartItemCreatedListener.php#L47-L87) -- [InvoicePaidListener.php:36-96](file://Listeners/InvoicePaidListener.php#L36-L96) -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [CartItemCreatedListener.php:47-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L47-L87) +- [InvoicePaidListener.php:36-96](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L36-L96) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) ## Performance Considerations - Real-time availability: Node selection and verification call into ResourceCalculationService, which fetches live data from Pterodactyl. This avoids stale cache but introduces external latency; batching is used internally to minimize API calls. @@ -297,10 +300,10 @@ Operational checks: - Inspect scheduler logs for cleanup runs and capacity alert checks. **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:335-382](file://Services/ReservationService.php#L335-L382) -- [InvoicePaidListener.php:58-125](file://Listeners/InvoicePaidListener.php#L58-L125) -- [DynamicPterodactyl.php:116-127](file://DynamicPterodactyl.php#L116-L127) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:335-382](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L335-L382) +- [InvoicePaidListener.php:58-125](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L58-L125) +- [DynamicPterodactyl.php:116-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L116-L127) ## Conclusion ReservationService provides a robust, auditable, and concurrent-safe mechanism to reserve compute resources during checkout. It combines strict state transitions, TTL enforcement, pessimistic locking with retries, and idempotent creation to protect against race conditions and duplicate allocations. Integration with Paymenter’s cart and invoice events ensures reservations are created automatically and confirmed reliably upon payment, while scheduled cleanup maintains data integrity and accurate availability. @@ -322,9 +325,9 @@ Expired --> [*] ``` **Diagram sources** -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) ### Idempotent Create Flow ```mermaid @@ -348,5 +351,5 @@ ThrowErr --> End ``` **Diagram sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:431-452](file://Services/ReservationService.php#L431-L452) \ No newline at end of file +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:431-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L431-L452) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md index dbe54de..f37090f 100644 --- a/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md +++ b/.qoder/repowiki/en/content/Core Services/ResourceCalculationService.md @@ -1,13 +1,16 @@ # ResourceCalculationService +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [NodeSelectionService.php](file://Services/NodeSelectionService.php) -- [api.php](file://routes/api.php) -- [ResourceCalculationServiceTest.php](file://tests/Unit/ResourceCalculationServiceTest.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [NodeSelectionService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php) +- [api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [ResourceCalculationServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php) ## Table of Contents @@ -50,13 +53,13 @@ RCS --> DB["Local DB
ptero_resource_reservations"] ``` **Diagram sources** -- [api.php:17-25](file://routes/api.php#L17-L25) -- [ResourceCalculationService.php:26-222](file://Services/ResourceCalculationService.php#L26-L222) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) +- [api.php:17-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L25) +- [ResourceCalculationService.php:26-222](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L222) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) **Section sources** -- [api.php:17-25](file://routes/api.php#L17-L25) +- [api.php:17-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L25) ## Core Components - ResourceCalculationService: Real-time availability calculations, cluster snapshot building, connection diagnostics, and verification against requirements. @@ -73,10 +76,10 @@ Responsibilities summary: - Expose verifyAvailability() to gate payment-time allocations **Section sources** -- [ResourceCalculationService.php:26-222](file://Services/ResourceCalculationService.php#L26-L222) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [ResourceCalculationService.php:26-222](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L222) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ## Architecture Overview The service uses a thin HTTP client wrapper around Pterodactyl’s Application API with retries on transient connection errors, strict timeouts, and sanitized error propagation. For cluster-wide snapshots, it batches node and server data retrieval to reduce API calls while preserving accuracy. @@ -108,10 +111,10 @@ RCS-->>Caller : Cluster snapshot or degraded snapshot ``` **Diagram sources** -- [ResourceCalculationService.php:26-141](file://Services/ResourceCalculationService.php#L26-L141) -- [ResourceCalculationService.php:313-406](file://Services/ResourceCalculationService.php#L313-L406) -- [ResourceCalculationService.php:407-486](file://Services/ResourceCalculationService.php#L407-L486) -- [ResourceCalculationService.php:487-631](file://Services/ResourceCalculationService.php#L487-L631) +- [ResourceCalculationService.php:26-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L141) +- [ResourceCalculationService.php:313-406](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L313-L406) +- [ResourceCalculationService.php:407-486](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L407-L486) +- [ResourceCalculationService.php:487-631](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L487-L631) ## Detailed Component Analysis @@ -147,11 +150,11 @@ Usage pattern example: - Called by NodeSelectionService to evaluate candidates and by AvailabilityController to expose location-level capacity. **Section sources** -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ResourceCalculationService.php:146-152](file://Services/ResourceCalculationService.php#L146-L152) -- [ResourceCalculationService.php:223-264](file://Services/ResourceCalculationService.php#L223-L264) -- [ResourceCalculationService.php:227-257](file://Services/ResourceCalculationService.php#L227-L257) -- [ResourceCalculationService.php:500-522](file://Services/ResourceCalculationService.php#L500-L522) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ResourceCalculationService.php:146-152](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L146-L152) +- [ResourceCalculationService.php:223-264](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L223-L264) +- [ResourceCalculationService.php:227-257](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L227-L257) +- [ResourceCalculationService.php:500-522](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L500-L522) ### Method: buildClusterSnapshot() Purpose: @@ -179,9 +182,9 @@ Degraded mode: - When Pterodactyl is unavailable, returns an empty snapshot plus an error marker so UIs remain usable. **Section sources** -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [ResourceCalculationService.php:291-357](file://Services/ResourceCalculationService.php#L291-L357) -- [ResourceCalculationService.php:393-417](file://Services/ResourceCalculationService.php#L393-L417) +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [ResourceCalculationService.php:291-357](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L291-L357) +- [ResourceCalculationService.php:393-417](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L393-L417) ### Method: verifyAvailability(nodeId, requirements, excludeReservationToken = null) Purpose: @@ -204,8 +207,8 @@ Use case: - Gate final confirmation to prevent race conditions between availability checks and payment completion. **Section sources** -- [ResourceCalculationService.php:197-214](file://Services/ResourceCalculationService.php#L197-L214) -- [ResourceCalculationService.php:524-534](file://Services/ResourceCalculationService.php#L524-L534) +- [ResourceCalculationService.php:197-214](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L197-L214) +- [ResourceCalculationService.php:524-534](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L524-L534) ### Method: testConnection() Purpose: @@ -220,7 +223,7 @@ Behavior: - Validates response shape and extracts useful metadata **Section sources** -- [ResourceCalculationService.php:154-195](file://Services/ResourceCalculationService.php#L154-L195) +- [ResourceCalculationService.php:154-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L154-L195) ### Internal helpers and integration points - pterodactylGet(): Centralized HTTP call with retry on connection errors, rate limit detection, and sanitized error messages. @@ -233,10 +236,10 @@ Integration with reservation system: - ReservationService uses pessimistic locking and idempotency keys to ensure safe creation and confirmation flows. **Section sources** -- [ResourceCalculationService.php:359-391](file://Services/ResourceCalculationService.php#L359-L391) -- [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) -- [ResourceCalculationService.php:487-631](file://Services/ResourceCalculationService.php#L487-L631) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [ResourceCalculationService.php:359-391](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L359-L391) +- [ResourceCalculationService.php:426-450](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L450) +- [ResourceCalculationService.php:487-631](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L487-L631) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) ### Class diagram ```mermaid @@ -285,10 +288,10 @@ ResourceCalculationService --> ResourceReservation : "reads pending" ``` **Diagram sources** -- [ResourceCalculationService.php:10-545](file://Services/ResourceCalculationService.php#L10-L545) -- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) -- [NodeSelectionService.php:5-88](file://Services/NodeSelectionService.php#L5-L88) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [ResourceCalculationService.php:10-545](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L10-L545) +- [ReservationService.php:16-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L453) +- [NodeSelectionService.php:5-88](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L5-L88) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ## Dependency Analysis - External dependency: Pterodactyl Application API via HTTP client @@ -309,9 +312,9 @@ External integrations: - Pterodactyl API rate limit awareness and retry behavior are implemented centrally in pterodactylGet(). **Section sources** -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) ## Performance Considerations - No caching: Real-time queries avoid staleness and overselling risks. @@ -356,11 +359,11 @@ Operational tips: - If frequent 5xx occur, consider increasing retry budgets or reducing snapshot frequency. **Section sources** -- [ResourceCalculationService.php:154-195](file://Services/ResourceCalculationService.php#L154-L195) -- [ResourceCalculationService.php:410-424](file://Services/ResourceCalculationService.php#L410-L424) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ResourceCalculationService.php:524-534](file://Services/ResourceCalculationService.php#L524-L534) -- [api.php:17-25](file://routes/api.php#L17-L25) +- [ResourceCalculationService.php:154-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L154-L195) +- [ResourceCalculationService.php:410-424](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L410-L424) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:524-534](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L524-L534) +- [api.php:17-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L25) ## Conclusion ResourceCalculationService provides accurate, real-time availability by querying Pterodactyl and accounting for pending reservations. Its design prioritizes correctness over speed: no caching, batched API calls, and robust error handling. Together with ReservationService and NodeSelectionService, it ensures that customers are offered realistic options and that the system prevents overselling throughout the checkout flow. diff --git a/.qoder/repowiki/en/content/Core Services/SliderConfigReaderService.md b/.qoder/repowiki/en/content/Core Services/SliderConfigReaderService.md index 9674e5a..fd58ef8 100644 --- a/.qoder/repowiki/en/content/Core Services/SliderConfigReaderService.md +++ b/.qoder/repowiki/en/content/Core Services/SliderConfigReaderService.md @@ -1,13 +1,16 @@ # SliderConfigReaderService +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [SliderConfigReaderService.php](file://Services/SliderConfigReaderService.php) -- [PricingController.php](file://Http/Controllers/Api/PricingController.php) -- [SliderConfigReaderServiceTest.php](file://tests/Unit/SliderConfigReaderServiceTest.php) -- [ConfigOptionSetupService.php](file://Services/ConfigOptionSetupService.php) -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [07-PRICING-MODELS.md](file://07-PRICING-MODELS.md) +- [SliderConfigReaderService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php) +- [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) +- [SliderConfigReaderServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/SliderConfigReaderServiceTest.php) +- [ConfigOptionSetupService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [07-PRICING-MODELS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/07-PRICING-MODELS.md) ## Table of Contents @@ -40,15 +43,15 @@ F["DynamicPterodactyl
Extension boot"] --> A ``` **Diagram sources** -- [PricingController.php:12-145](file://Http/Controllers/Api/PricingController.php#L12-L145) -- [SliderConfigReaderService.php:7-66](file://Services/SliderConfigReaderService.php#L7-L66) -- [ConfigOptionSetupService.php:117-171](file://Services/ConfigOptionSetupService.php#L117-L171) -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [07-PRICING-MODELS.md:19-27](file://07-PRICING-MODELS.md#L19-L27) +- [PricingController.php:12-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L12-L145) +- [SliderConfigReaderService.php:7-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L7-L66) +- [ConfigOptionSetupService.php:117-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L117-L171) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [07-PRICING-MODELS.md:19-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/07-PRICING-MODELS.md#L19-L27) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [PricingController.php:12-145](file://Http/Controllers/Api/PricingController.php#L12-L145) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [PricingController.php:12-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L12-L145) ## Core Components - SliderConfigReaderService: Reads and normalizes slider metadata for a product into a stable structure suitable for frontend rendering. @@ -62,10 +65,10 @@ Key responsibilities: - Never compute prices; delegate pricing to core methods invoked elsewhere. **Section sources** -- [SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) -- [PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) -- [ConfigOptionSetupService.php:117-171](file://Services/ConfigOptionSetupService.php#L117-L171) -- [07-PRICING-MODELS.md:19-27](file://07-PRICING-MODELS.md#L19-L27) +- [SliderConfigReaderService.php:14-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L53) +- [PricingController.php:24-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L145) +- [ConfigOptionSetupService.php:117-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L117-L171) +- [07-PRICING-MODELS.md:19-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/07-PRICING-MODELS.md#L19-L27) ## Architecture Overview The service is part of a read path that powers the frontend’s dynamic sliders. Controllers request slider configuration, which the service resolves from database-backed ConfigOptions marked as dynamic_slider. Pricing calculations are performed separately by core methods and aggregated by the controller. @@ -92,9 +95,9 @@ PC-->>FE : JSON response with total and breakdown ``` **Diagram sources** -- [PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) -- [SliderConfigReaderService.php:14-66](file://Services/SliderConfigReaderService.php#L14-L66) -- [07-PRICING-MODELS.md:19-27](file://07-PRICING-MODELS.md#L19-L27) +- [PricingController.php:24-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L145) +- [SliderConfigReaderService.php:14-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L66) +- [07-PRICING-MODELS.md:19-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/07-PRICING-MODELS.md#L19-L27) ## Detailed Component Analysis @@ -150,12 +153,12 @@ Next -- "No" --> ReturnFull["Return { has_config: true, sliders: {...} }"] ``` **Diagram sources** -- [SliderConfigReaderService.php:14-66](file://Services/SliderConfigReaderService.php#L14-L66) +- [SliderConfigReaderService.php:14-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L66) **Section sources** -- [SliderConfigReaderService.php:14-66](file://Services/SliderConfigReaderService.php#L14-L66) -- [SliderConfigReaderServiceTest.php:25-68](file://tests/Unit/SliderConfigReaderServiceTest.php#L25-L68) -- [SliderConfigReaderServiceTest.php:92-132](file://tests/Unit/SliderConfigReaderServiceTest.php#L92-L132) +- [SliderConfigReaderService.php:14-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L66) +- [SliderConfigReaderServiceTest.php:25-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/SliderConfigReaderServiceTest.php#L25-L68) +- [SliderConfigReaderServiceTest.php:92-132](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/SliderConfigReaderServiceTest.php#L92-L132) ### PricingController Integration Responsibilities: @@ -191,12 +194,12 @@ PC-->>FE : JSON with total and breakdown ``` **Diagram sources** -- [PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) -- [07-PRICING-MODELS.md:19-27](file://07-PRICING-MODELS.md#L19-L27) +- [PricingController.php:24-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L145) +- [07-PRICING-MODELS.md:19-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/07-PRICING-MODELS.md#L19-L27) **Section sources** -- [PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) -- [07-PRICING-MODELS.md:19-27](file://07-PRICING-MODELS.md#L19-L27) +- [PricingController.php:24-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L145) +- [07-PRICING-MODELS.md:19-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/07-PRICING-MODELS.md#L19-L27) ### ConfigOptionSetupService and Metadata Schema Role: @@ -234,12 +237,12 @@ ConfigOptionSetupService --> ConfigOption : "creates/updates" ``` **Diagram sources** -- [ConfigOptionSetupService.php:44-171](file://Services/ConfigOptionSetupService.php#L44-L171) +- [ConfigOptionSetupService.php:44-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L171) **Section sources** -- [ConfigOptionSetupService.php:117-171](file://Services/ConfigOptionSetupService.php#L117-L171) -- [07-PRICING-MODELS.md:31-53](file://07-PRICING-MODELS.md#L31-L53) -- [07-PRICING-MODELS.md:290-329](file://07-PRICING-MODELS.md#L290-L329) +- [ConfigOptionSetupService.php:117-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L117-L171) +- [07-PRICING-MODELS.md:31-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/07-PRICING-MODELS.md#L31-L53) +- [07-PRICING-MODELS.md:290-329](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/07-PRICING-MODELS.md#L290-L329) ### Example Slider Configuration Structures Typical structures produced by the service for frontend consumption: @@ -257,8 +260,8 @@ Typical structures produced by the service for frontend consumption: These structures are derived from ConfigOption metadata and normalized to ensure consistent keys and defaults even if some fields are missing. **Section sources** -- [SliderConfigReaderService.php:27-52](file://Services/SliderConfigReaderService.php#L27-L52) -- [SliderConfigReaderServiceTest.php:25-68](file://tests/Unit/SliderConfigReaderServiceTest.php#L25-L68) +- [SliderConfigReaderService.php:27-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L27-L52) +- [SliderConfigReaderServiceTest.php:25-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/SliderConfigReaderServiceTest.php#L25-L68) ### Error Handling for Missing or Invalid Configurations - No sliders found: getConfig returns has_config=false and empty sliders; controller responds with a 404-style message. @@ -266,10 +269,10 @@ These structures are derived from ConfigOption metadata and normalized to ensure - Calculation failures: Controller catches exceptions during pricing calculation and returns a structured error response, optionally including debug details when enabled. **Section sources** -- [SliderConfigReaderService.php:18-23](file://Services/SliderConfigReaderService.php#L18-L23) -- [SliderConfigReaderService.php:27-31](file://Services/SliderConfigReaderService.php#L27-L31) -- [PricingController.php:36-41](file://Http/Controllers/Api/PricingController.php#L36-L41) -- [PricingController.php:104-121](file://Http/Controllers/Api/PricingController.php#L104-L121) +- [SliderConfigReaderService.php:18-23](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L18-L23) +- [SliderConfigReaderService.php:27-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L27-L31) +- [PricingController.php:36-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L36-L41) +- [PricingController.php:104-121](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L104-L121) ### Integration Patterns with Other Services - PricingController depends on SliderConfigReaderService via constructor injection to fetch slider definitions. @@ -278,10 +281,10 @@ These structures are derived from ConfigOption metadata and normalized to ensure - Extension boot process registers routes and schedules but does not interfere with pricing logic. **Section sources** -- [PricingController.php:12-19](file://Http/Controllers/Api/PricingController.php#L12-L19) -- [PricingController.php:69-94](file://Http/Controllers/Api/PricingController.php#L69-L94) -- [ConfigOptionSetupService.php:44-171](file://Services/ConfigOptionSetupService.php#L44-L171) -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) +- [PricingController.php:12-19](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L12-L19) +- [PricingController.php:69-94](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L69-L94) +- [ConfigOptionSetupService.php:44-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L171) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) ## Dependency Analysis Coupling and cohesion: @@ -310,14 +313,14 @@ W["ConfigOptionSetupService"] --> M ``` **Diagram sources** -- [SliderConfigReaderService.php:5-66](file://Services/SliderConfigReaderService.php#L5-L66) -- [PricingController.php:12-145](file://Http/Controllers/Api/PricingController.php#L12-L145) -- [ConfigOptionSetupService.php:44-171](file://Services/ConfigOptionSetupService.php#L44-L171) +- [SliderConfigReaderService.php:5-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L5-L66) +- [PricingController.php:12-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L12-L145) +- [ConfigOptionSetupService.php:44-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L171) **Section sources** -- [SliderConfigReaderService.php:5-66](file://Services/SliderConfigReaderService.php#L5-L66) -- [PricingController.php:12-145](file://Http/Controllers/Api/PricingController.php#L12-L145) -- [ConfigOptionSetupService.php:44-171](file://Services/ConfigOptionSetupService.php#L44-L171) +- [SliderConfigReaderService.php:5-66](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L5-L66) +- [PricingController.php:12-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L12-L145) +- [ConfigOptionSetupService.php:44-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L171) ## Performance Considerations - Query efficiency: The service filters by product and type, minimizing result sets. @@ -344,9 +347,9 @@ Operational tips: - Ensure pricing metadata matches supported models (linear, tiered, base_addon). **Section sources** -- [PricingController.php:36-41](file://Http/Controllers/Api/PricingController.php#L36-L41) -- [PricingController.php:104-121](file://Http/Controllers/Api/PricingController.php#L104-L121) -- [ConfigOptionSetupService.php:124-131](file://Services/ConfigOptionSetupService.php#L124-L131) +- [PricingController.php:36-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L36-L41) +- [PricingController.php:104-121](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L104-L121) +- [ConfigOptionSetupService.php:124-131](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L124-L131) ## Conclusion SliderConfigReaderService provides a clean, read-only interface to dynamic slider configuration for Paymenter products. It abstracts away metadata variations and delivers a stable structure to the frontend while delegating pricing calculations to Paymenter core. Its tight integration with PricingController and compatibility with ConfigOptionSetupService ensures consistent configuration lifecycle management. By adhering to separation of concerns, the service remains simple, testable, and resilient to configuration edge cases. @@ -376,5 +379,5 @@ SliderConfigReaderService provides a clean, read-only interface to dynamic slide - model: pricing model used **Section sources** -- [PricingController.php:24-145](file://Http/Controllers/Api/PricingController.php#L24-L145) -- [07-PRICING-MODELS.md:290-329](file://07-PRICING-MODELS.md#L290-L329) \ No newline at end of file +- [PricingController.php:24-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L145) +- [07-PRICING-MODELS.md:290-329](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/07-PRICING-MODELS.md#L290-L329) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Database Schema/Resource Reservations Table.md b/.qoder/repowiki/en/content/Database Schema/Resource Reservations Table.md index cbadded..e07e706 100644 --- a/.qoder/repowiki/en/content/Database Schema/Resource Reservations Table.md +++ b/.qoder/repowiki/en/content/Database Schema/Resource Reservations Table.md @@ -1,17 +1,20 @@ # Resource Reservations Table +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) -- [2026_04_22_000001_drop_released_from_reservation_status.php](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [ReservationController.php](file://Http/Controllers/Api/ReservationController.php) -- [AdminReservationController.php](file://Http/Controllers/Api/Admin/AdminReservationController.php) -- [CartItemCreatedListener.php](file://Listeners/CartItemCreatedListener.php) -- [StoreReservationRequest.php](file://Http/Requests/StoreReservationRequest.php) -- [ResourceReservationPolicy.php](file://Policies/ResourceReservationPolicy.php) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) +- [2026_04_22_000001_drop_released_from_reservation_status.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) +- [AdminReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php) +- [CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php) +- [StoreReservationRequest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php) +- [ResourceReservationPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php) ## Table of Contents @@ -57,23 +60,23 @@ RQ --> C ``` **Diagram sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) -- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [AdminReservationController.php:9-75](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) -- [CartItemCreatedListener.php:11-173](file://Listeners/CartItemCreatedListener.php#L11-L173) -- [StoreReservationRequest.php:10-162](file://Http/Requests/StoreReservationRequest.php#L10-L162) -- [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [ReservationService.php:16-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L453) +- [ReservationController.php:13-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminReservationController.php:9-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) +- [CartItemCreatedListener.php:11-173](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L11-L173) +- [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) +- [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) **Section sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) -- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [AdminReservationController.php:9-75](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) -- [CartItemCreatedListener.php:11-173](file://Listeners/CartItemCreatedListener.php#L11-L173) -- [StoreReservationRequest.php:10-162](file://Http/Requests/StoreReservationRequest.php#L10-L162) -- [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [ReservationService.php:16-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L453) +- [ReservationController.php:13-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminReservationController.php:9-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) +- [CartItemCreatedListener.php:11-173](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L11-L173) +- [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) +- [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) ## Core Components - Schema and constraints are defined in the initial migration and subsequent migrations that adjust status values and add idempotency support. @@ -85,16 +88,16 @@ RQ --> C - ResourceReservationPolicy enforces authorization rules for viewing, confirming, cancelling, and extending reservations. **Section sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-31](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L31) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [ReservationService.php:16-453](file://Services/ReservationService.php#L16-L453) -- [ReservationController.php:13-137](file://Http/Controllers/Api/ReservationController.php#L13-L137) -- [AdminReservationController.php:9-75](file://Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) -- [CartItemCreatedListener.php:11-173](file://Listeners/CartItemCreatedListener.php#L11-L173) -- [StoreReservationRequest.php:10-162](file://Http/Requests/StoreReservationRequest.php#L10-L162) -- [ResourceReservationPolicy.php:9-69](file://Policies/ResourceReservationPolicy.php#L9-L69) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L31) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [ReservationService.php:16-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L453) +- [ReservationController.php:13-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L13-L137) +- [AdminReservationController.php:9-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L9-L75) +- [CartItemCreatedListener.php:11-173](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L11-L173) +- [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) +- [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) ## Architecture Overview The reservation lifecycle ensures temporary resource holds until payment completes or TTL expires. Creation uses pessimistic locking to avoid overselling, and idempotency prevents duplicate reservations under concurrent requests. Status transitions are enforced at the service layer with authorization checks via policies. @@ -124,14 +127,14 @@ Controller-->>Client : result ``` **Diagram sources** -- [ReservationController.php:24-79](file://Http/Controllers/Api/ReservationController.php#L24-L79) -- [ReservationService.php:43-199](file://Services/ReservationService.php#L43-L199) -- [ResourceReservationPolicy.php:55-58](file://Policies/ResourceReservationPolicy.php#L55-L58) +- [ReservationController.php:24-79](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L79) +- [ReservationService.php:43-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L199) +- [ResourceReservationPolicy.php:55-58](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L55-L58) **Section sources** -- [ReservationController.php:24-79](file://Http/Controllers/Api/ReservationController.php#L24-L79) -- [ReservationService.php:43-199](file://Services/ReservationService.php#L43-L199) -- [ResourceReservationPolicy.php:55-58](file://Policies/ResourceReservationPolicy.php#L55-L58) +- [ReservationController.php:24-79](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L79) +- [ReservationService.php:43-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L199) +- [ResourceReservationPolicy.php:55-58](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L55-L58) ## Detailed Component Analysis @@ -177,9 +180,9 @@ Foreign Keys: - user_id -> users(id) on delete set null **Section sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-31](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L31) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L31) ### Eloquent Model: ResourceReservation - Fillable fields include token, idempotency_key, cart_item_id, service_id, user_id, node_id, location_id, memory, cpu, disk, calculated_price, pricing_breakdown, status, admin_notes, expires_at @@ -195,7 +198,7 @@ Foreign Keys: - belongsTo Service **Section sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ### Service Layer: ReservationService Key responsibilities: @@ -230,11 +233,11 @@ Concurrency and safety: - Idempotency duplicate detection and handling **Section sources** -- [ReservationService.php:43-199](file://Services/ReservationService.php#L43-L199) -- [ReservationService.php:208-281](file://Services/ReservationService.php#L208-L281) -- [ReservationService.php:312-382](file://Services/ReservationService.php#L312-L382) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [ReservationService.php:431-452](file://Services/ReservationService.php#L431-L452) +- [ReservationService.php:43-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L199) +- [ReservationService.php:208-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L281) +- [ReservationService.php:312-382](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L312-L382) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [ReservationService.php:431-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L431-L452) ### API Controllers - Customer-facing ReservationController: @@ -250,9 +253,9 @@ Authorization: - Policies enforce ownership for view/cancel/extend and allow admin panel access for broader operations **Section sources** -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [AdminReservationController.php:18-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) -- [ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [AdminReservationController.php:18-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L74) +- [ResourceReservationPolicy.php:14-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L68) ### Request Validation: StoreReservationRequest - Validates product_id, location_id, resource sliders (memory, cpu, disk) @@ -262,7 +265,7 @@ Authorization: - Supports idempotency_key via header or body **Section sources** -- [StoreReservationRequest.php:12-162](file://Http/Requests/StoreReservationRequest.php#L12-L162) +- [StoreReservationRequest.php:12-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L12-L162) ### Listener: CartItemCreatedListener - Detects products with dynamic_slider config options @@ -272,8 +275,8 @@ Authorization: - Logs errors without blocking cart operations **Section sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemCreatedListener.php:93-172](file://Listeners/CartItemCreatedListener.php#L93-L172) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemCreatedListener.php:93-172](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L93-L172) ### Authorization: ResourceReservationPolicy - Admin bypass for panel access @@ -281,7 +284,7 @@ Authorization: - Admin-only viewAny for listing all reservations **Section sources** -- [ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) +- [ResourceReservationPolicy.php:14-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L68) ## Dependency Analysis The reservation table depends on external entities through foreign keys and is consumed by multiple application layers. @@ -324,8 +327,8 @@ USERS ||--o{ PTERO_RESOURCE_RESERVATIONS : "user_id" ``` **Diagram sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-31](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L31) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:9-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L9-L31) Coupling and cohesion: - High cohesion within ReservationService for state transitions and TTL management @@ -341,9 +344,9 @@ External integrations: - Audit logging via extension actions **Section sources** -- [ReservationService.php:43-199](file://Services/ReservationService.php#L43-L199) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) +- [ReservationService.php:43-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L199) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) ## Performance Considerations Index strategies: @@ -384,10 +387,10 @@ Operational checks: - Validate foreign key integrity for cart_item_id, service_id, user_id **Section sources** -- [ReservationService.php:43-199](file://Services/ReservationService.php#L43-L199) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [AdminReservationController.php:36-74](file://Http/Controllers/Api/Admin/AdminReservationController.php#L36-L74) -- [StoreReservationRequest.php:51-112](file://Http/Requests/StoreReservationRequest.php#L51-L112) +- [ReservationService.php:43-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L199) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [AdminReservationController.php:36-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L36-L74) +- [StoreReservationRequest.php:51-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L51-L112) ## Conclusion The resource reservations table provides a robust mechanism to temporarily reserve Pterodactyl node resources during checkout, ensuring consistency through pessimistic locking, idempotency, and strict status transitions. Its schema supports token-based tracking, cart and service relationships, user associations, and precise resource accounting. With targeted indexes and service-layer logic, it scales to handle large datasets while maintaining performance and reliability. @@ -409,9 +412,9 @@ cancelled --> [*] ``` **Diagram sources** -- [ReservationService.php:166-199](file://Services/ReservationService.php#L166-L199) -- [ReservationService.php:208-241](file://Services/ReservationService.php#L208-L241) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) +- [ReservationService.php:166-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L199) +- [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) ### Common Query Patterns - Find pending non-expired reservations for a location: @@ -422,5 +425,5 @@ cancelled --> [*] - Filter by status, location_id, node_id, user_id; order by created_at desc; paginate **Section sources** -- [ReservationService.php:312-382](file://Services/ReservationService.php#L312-L382) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) \ No newline at end of file +- [ReservationService.php:312-382](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L312-L382) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index 4fa2b01..5e39d9a 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -1,19 +1,45 @@ # Deployment +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + +## Current Deployment Gate + +Deploy the extension only with the reviewed Paymenter companion commit recorded +by the cross-repository workflow. Before enabling dynamic stock: + +1. Back up Paymenter and run both repositories' migrations. +2. Configure a canonical HTTPS panel URL and an application API key with read + access to locations, nodes, servers, and allocations. +3. Create a `NodeCapacityPolicy` for every eligible node. CPU is local policy; + stock Pterodactyl does not provide a `cpu_threads` node field. +4. Confirm exclusive provisioning control for every eligible node. Out-of-band + server moves, resizes, creates, or allocation assignments invalidate the + reservation guarantee. +5. Run the setup wizard, the cross-repository PHPUnit workflow, scheduler + heartbeat checks, and a read-only live inventory smoke test. +6. Resume deployment synchronization only after the exact commits are reviewed + and approved. + +The API key migration encrypts the stored credential. Customer errors remain +generic; detailed upstream failures belong only in protected logs. + +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/09-IMPLEMENTATION.md) + + **Referenced Files in This Document** -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [api.php](file://routes/api.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) -- [2025_01_01_000003_create_ptero_audit_logs_table.php](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) -- [2025_01_01_000004_create_ptero_alert_configs_table.php](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php) -- [phpunit.xml](file://phpunit.xml) -- [AGENTS.md](file://AGENTS.md) -- [DECISIONS.md](file://DECISIONS.md) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) +- [2025_01_01_000003_create_ptero_audit_logs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) +- [2025_01_01_000004_create_ptero_alert_configs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php) +- [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) +- [AGENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/AGENTS.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md) ## Table of Contents @@ -54,14 +80,14 @@ G --> I["Database (ptero_* tables)"] ``` **Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [api.php:17-40](file://routes/api.php#L17-L40) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) **Section sources** -- [DynamicPterodactyl.php:25-32](file://DynamicPterodactyl.php#L25-L32) -- [DynamicPterodactyl.php:77-91](file://DynamicPterodactyl.php#L77-L91) -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [api.php:17-40](file://routes/api.php#L17-L40) +- [DynamicPterodactyl.php:25-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L25-L32) +- [DynamicPterodactyl.php:77-91](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L77-L91) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ## Core Components - Extension lifecycle: installs/uninstalls migrations, boots routes, policies, observers, event listeners, and scheduled jobs. @@ -71,10 +97,10 @@ G --> I["Database (ptero_* tables)"] - Audit and alerts: records state transitions and sends capacity alerts based on configured thresholds and cooldowns. **Section sources** -- [DynamicPterodactyl.php:77-127](file://DynamicPterodactyl.php#L77-L127) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [api.php:17-40](file://routes/api.php#L17-L40) +- [DynamicPterodactyl.php:77-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L77-L127) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ## Architecture Overview The extension integrates with Paymenter events and the Pterodactyl Panel API to provide real-time availability and short-term reservations. Schedules run cleanup and alert checks. All customer-facing responses expose only aggregate capacity; node-level detail is admin-only. @@ -108,10 +134,10 @@ Res-->>Client : reservation token + expiry ``` **Diagram sources** -- [api.php:17-30](file://routes/api.php#L17-L30) -- [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [api.php:17-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L30) +- [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) ## Detailed Component Analysis @@ -130,9 +156,9 @@ Important notes: - The scheduler must be active; schedules are defined inline in the extension boot method. **Section sources** -- [DynamicPterodactyl.php:77-91](file://DynamicPterodactyl.php#L77-L91) -- [DynamicPterodactyl.php:116-127](file://DynamicPterodactyl.php#L116-L127) -- [AGENTS.md:90-100](file://AGENTS.md#L90-L100) +- [DynamicPterodactyl.php:77-91](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L77-L91) +- [DynamicPterodactyl.php:116-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L116-L127) +- [AGENTS.md:90-100](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/AGENTS.md#L90-L100) ### Environment Configuration Requirements Configure the following settings in the extension configuration: @@ -147,9 +173,9 @@ Operational requirements: - Node payloads must provide an integer `cpu_threads` capacity value; missing, fractional, or malformed node/server capacity fields and incomplete pagination fail closed instead of advertising unverified capacity. Stock Pterodactyl does not expose this node field and uses zero server limits to mean unlimited, while this branch does not yet encrypt/migrate the stored API key. Keep deployment paused until PR #22 is fully rebased so its `NodeCapacityPolicy`, zero-as-unlimited rejection, and API-key encryption migration are all retained alongside every PR #23 safety and Wiki change. A partial CPU-only cherry-pick is not deployable. **Section sources** -- [DynamicPterodactyl.php:48-75](file://DynamicPterodactyl.php#L48-L75) -- [ResourceCalculationService.php:16-21](file://Services/ResourceCalculationService.php#L16-L21) -- [ReservationService.php:24-35](file://Services/ReservationService.php#L24-L35) +- [DynamicPterodactyl.php:48-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L48-L75) +- [ResourceCalculationService.php:16-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L16-L21) +- [ReservationService.php:24-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L24-L35) ### Database Schema and Migrations The extension creates and manages the following tables: @@ -168,10 +194,10 @@ Indexes and constraints: - Alert configs include indexes for location_id and is_active. **Section sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) ### API Endpoints and Rate Limits Customer-facing endpoints (throttled at 30 requests per minute): @@ -196,8 +222,8 @@ Security and authorization: - Admin endpoints require authentication and admin role. **Section sources** -- [api.php:17-40](file://routes/api.php#L17-L40) -- [AvailabilityController.php:22-71](file://Http/Controllers/Api/AvailabilityController.php#L22-L71) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [AvailabilityController.php:22-71](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L71) ### Reservation Lifecycle and Concurrency Lifecycle states: @@ -232,13 +258,13 @@ Audit --> Done(["Return reservation token"]) ``` **Diagram sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:384-405](file://Services/ReservationService.php#L384-L405) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:384-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L384-L405) **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:384-405](file://Services/ReservationService.php#L384-L405) -- [DECISIONS.md:233-235](file://DECISIONS.md#L233-L235) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:384-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L384-L405) +- [DECISIONS.md:233-235](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L233-L235) ### Capacity Calculation and Real-Time API Usage - Availability is always read from the Pterodactyl Panel API; results are not cached. @@ -264,12 +290,12 @@ Cap-->>Caller : cluster snapshot (locations, nodes, by_location) ``` **Diagram sources** -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [ResourceCalculationService.php:426-450](file://Services/ResourceCalculationService.php#L426-L450) +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [ResourceCalculationService.php:426-450](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L426-L450) **Section sources** -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) ### Monitoring Setup for API Rate Limits and Database Performance Monitoring priorities: @@ -284,9 +310,9 @@ Recommended metrics: - Alert delivery success rate and last successful delivery timestamp. **Section sources** -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ReservationService.php:384-405](file://Services/ReservationService.php#L384-L405) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [ReservationService.php:384-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L384-L405) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) ### Backup Strategies for Reservation and Audit Data Backup targets: @@ -300,10 +326,10 @@ Recommendations: - Retain audit logs according to retention policy; consider archiving older entries to reduce query load. **Section sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) ### Scaling Considerations for High-Volume Deployments - Throttle compliance: Respect route-level throttles (30/min for availability/pricing, 10/min for reservations). @@ -313,9 +339,9 @@ Recommendations: - Degraded mode: When Panel is down, availability endpoints may return degraded snapshots; design UI to handle this gracefully. **Section sources** -- [api.php:17-40](file://routes/api.php#L17-L40) -- [DynamicPterodactyl.php:116-127](file://DynamicPterodactyl.php#L116-L127) -- [ResourceCalculationService.php:403-417](file://Services/ResourceCalculationService.php#L403-L417) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [DynamicPterodactyl.php:116-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L116-L127) +- [ResourceCalculationService.php:403-417](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L403-L417) ### Maintenance Procedures - Run the scheduler continuously to execute cleanup and alert checks. @@ -324,8 +350,8 @@ Recommendations: - Validate Pterodactyl API connectivity using the test connection capability. **Section sources** -- [DynamicPterodactyl.php:116-127](file://DynamicPterodactyl.php#L116-L127) -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) +- [DynamicPterodactyl.php:116-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L116-L127) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) ### Upgrade Paths, Version Compatibility, and Rollback Procedures - Version: The extension declares version 3.1.0 in its metadata. @@ -342,9 +368,9 @@ Recommendations: Note: Pricing logic is owned by Paymenter core; avoid adding pricing storage or logic to the extension. **Section sources** -- [DynamicPterodactyl.php:25-32](file://DynamicPterodactyl.php#L25-L32) -- [DynamicPterodactyl.php:77-91](file://DynamicPterodactyl.php#L77-L91) -- [DECISIONS.md:213-228](file://DECISIONS.md#L213-L228) +- [DynamicPterodactyl.php:25-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L25-L32) +- [DynamicPterodactyl.php:77-91](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L77-L91) +- [DECISIONS.md:213-228](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L213-L228) ### Production Readiness Checklist Security hardening: @@ -372,10 +398,10 @@ Testing isolation: - Tests enforce isolated cache/session/queue/mail settings; production should use appropriate stores. **Section sources** -- [api.php:32-40](file://routes/api.php#L32-L40) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) -- [DynamicPterodactyl.php:116-127](file://DynamicPterodactyl.php#L116-L127) -- [phpunit.xml:28-41](file://phpunit.xml#L28-L41) +- [api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L32-L40) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [DynamicPterodactyl.php:116-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L116-L127) +- [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) ## Dependency Analysis Runtime dependencies: @@ -403,14 +429,14 @@ Models["Models"] --> DB ``` **Diagram sources** -- [api.php:17-40](file://routes/api.php#L17-L40) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) **Section sources** -- [api.php:17-40](file://routes/api.php#L17-L40) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) ## Performance Considerations - Use throttling to protect both Paymenter and Pterodactyl APIs. @@ -434,9 +460,9 @@ Diagnostic steps: - Validate scheduler tasks are running and not overlapping. **Section sources** -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) ## Conclusion Deploying the Dynamic Pterodactyl extension requires careful configuration of Pterodactyl API credentials, scheduler operation, and database readiness. Adhering to throttling, real-time availability, and robust reservation handling ensures reliable operations. Monitoring, backups, and maintenance procedures safeguard production stability. Follow the upgrade and rollback guidance to maintain compatibility with Paymenter core and Filament v4. @@ -450,11 +476,11 @@ Deploying the Dynamic Pterodactyl extension requires careful configuration of Pt - Check capacity alerts: Runs every five minutes, enforces cooldown and delivers notifications. **Section sources** -- [DynamicPterodactyl.php:116-127](file://DynamicPterodactyl.php#L116-L127) +- [DynamicPterodactyl.php:116-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L116-L127) ### Appendix B: Test Harness Isolation - phpunit.xml enforces isolated cache/session/queue/mail settings and a test database name guard. - Ensure tests are run against a dedicated test database to avoid polluting shared stores. **Section sources** -- [phpunit.xml:28-41](file://phpunit.xml#L28-L41) +- [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index cedba23..af44888 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -1,19 +1,37 @@ # Event System +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + +## Current Event Contract + +The extension registers `CartItemCreatedListener` for cart create/update events +and `CartItemDeletedListener` for removal. They adapt Paymenter's transactional +cart operations to `ReservationService`; capacity failure is allowed to bubble +so the cart mutation rolls back. + +Paid service and service-upgrade transitions are owned by the matching Paymenter +companion lifecycle. The reconciled extension does not register +`InvoicePaidListener` or `ServiceCreatedListener`. Scheduled reservation +cleanup, reconciliation, capacity alerts, and scheduler-lag checks are +registered from `DynamicPterodactyl::boot()`. + +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/04-EVENTS.md) + + **Referenced Files in This Document** -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [CartItemCreatedListener.php](file://Listeners/CartItemCreatedListener.php) -- [CartItemDeletedListener.php](file://Listeners/CartItemDeletedListener.php) -- [InvoicePaidListener.php](file://Listeners/InvoicePaidListener.php) -- [ServiceCreatedListener.php](file://Listeners/ServiceCreatedListener.php) -- [AlertDeliveryFailed.php](file://Events/AlertDeliveryFailed.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [AlertService.php](file://Services/AlertService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [AlertDeliveryLog.php](file://Models/AlertDeliveryLog.php) -- [CartItemDeletedListenerTest.php](file://tests/Unit/CartItemDeletedListenerTest.php) -- [InvoicePaidListenerTest.php](file://tests/Unit/InvoicePaidListenerTest.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php) +- [CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php) +- [InvoicePaidListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php) +- [ServiceCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php) +- [AlertDeliveryFailed.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [AlertDeliveryLog.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php) +- [CartItemDeletedListenerTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/CartItemDeletedListenerTest.php) +- [InvoicePaidListenerTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/InvoicePaidListenerTest.php) ## Table of Contents @@ -60,12 +78,12 @@ E --> I["AlertDeliveryFailed Event"] ``` **Diagram sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [AlertService.php:128-247](file://Services/AlertService.php#L128-L247) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) +- [AlertService.php:128-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L247) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) **Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) ## Core Components - Event listeners: @@ -83,15 +101,15 @@ E --> I["AlertDeliveryFailed Event"] - AlertDeliveryLog: records attempted delivery outcomes **Section sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) -- [ReservationService.php:43-405](file://Services/ReservationService.php#L43-L405) -- [AlertService.php:33-247](file://Services/AlertService.php#L33-L247) -- [AlertDeliveryFailed.php:9-16](file://Events/AlertDeliveryFailed.php#L9-L16) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) +- [ReservationService.php:43-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L405) +- [AlertService.php:33-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L247) +- [AlertDeliveryFailed.php:9-16](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L16) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) ## Architecture Overview The checkout process spans multiple Paymenter events and extension services: @@ -132,11 +150,11 @@ L3->>L3 : Log linkage (ServiceCreatedListener) ``` **Diagram sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [ReservationService.php:43-199](file://Services/ReservationService.php#L43-L199) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [ReservationService.php:43-199](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L199) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) ## Detailed Component Analysis @@ -156,10 +174,10 @@ Register --> Sched2["Schedule: check capacity alerts"] ``` **Diagram sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) **Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) ### CartItemCreatedListener Responsibilities: @@ -173,8 +191,8 @@ Error handling: - Non-fatal exceptions are caught and logged; checkout continues even if reservation creation fails **Section sources** -- [CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [CartItemCreatedListener.php:93-172](file://Listeners/CartItemCreatedListener.php#L93-L172) +- [CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [CartItemCreatedListener.php:93-172](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L93-L172) ### CartItemDeletedListener Responsibilities: @@ -190,8 +208,8 @@ Edge cases covered by tests: - Exception path logging without rethrow **Section sources** -- [CartItemDeletedListener.php:12-57](file://Listeners/CartItemDeletedListener.php#L12-L57) -- [CartItemDeletedListenerTest.php:21-125](file://tests/Unit/CartItemDeletedListenerTest.php#L21-L125) +- [CartItemDeletedListener.php:12-57](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L12-L57) +- [CartItemDeletedListenerTest.php:21-125](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/CartItemDeletedListenerTest.php#L21-L125) ### InvoicePaidListener Responsibilities: @@ -207,8 +225,8 @@ Error handling: - State drift scenarios trigger targeted notifications with reasons **Section sources** -- [InvoicePaidListener.php:14-133](file://Listeners/InvoicePaidListener.php#L14-L133) -- [InvoicePaidListenerTest.php:25-101](file://tests/Unit/InvoicePaidListenerTest.php#L25-L101) +- [InvoicePaidListener.php:14-133](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L14-L133) +- [InvoicePaidListenerTest.php:25-101](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/InvoicePaidListenerTest.php#L25-L101) ### ServiceCreatedListener Responsibilities: @@ -217,7 +235,7 @@ Responsibilities: - Assumes confirmation has already occurred via InvoicePaidListener **Section sources** -- [ServiceCreatedListener.php:10-31](file://Listeners/ServiceCreatedListener.php#L10-L31) +- [ServiceCreatedListener.php:10-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/ServiceCreatedListener.php#L10-L31) ### AlertDeliveryFailed Event Purpose: @@ -231,8 +249,8 @@ Usage: - Subscribers can listen to this event to implement custom failure handling, retries, or escalation **Section sources** -- [AlertDeliveryFailed.php:9-16](file://Events/AlertDeliveryFailed.php#L9-L16) -- [AlertService.php:218-236](file://Services/AlertService.php#L218-L236) +- [AlertDeliveryFailed.php:9-16](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L16) +- [AlertService.php:218-236](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L218-L236) ### ReservationService Key behaviors: @@ -249,10 +267,10 @@ Concurrency and reliability: - Safe auditing for all mutations **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L281) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ### AlertService Key behaviors: @@ -267,11 +285,11 @@ Failure handling: - Logs detailed context for each channel attempt and failure **Section sources** -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:128-247](file://Services/AlertService.php#L128-L247) -- [AlertService.php:250-299](file://Services/AlertService.php#L250-L299) -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertService.php:128-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L247) +- [AlertService.php:250-299](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L250-L299) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) ## Dependency Analysis High-level dependencies among components: @@ -293,14 +311,14 @@ AS --> LOG["AlertDeliveryLog"] ``` **Diagram sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [AlertService.php:128-247](file://Services/AlertService.php#L128-L247) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) +- [AlertService.php:128-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L247) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) **Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [AlertService.php:128-247](file://Services/AlertService.php#L128-L247) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) +- [AlertService.php:128-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L247) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) ## Performance Considerations - Database locking: Reservation creation uses pessimistic locks to avoid races and deadlocks; retry logic improves resilience under contention. @@ -332,12 +350,12 @@ Debugging tips: - For unit testing, mock services and assert log messages and service interactions **Section sources** -- [CartItemCreatedListener.php:79-86](file://Listeners/CartItemCreatedListener.php#L79-L86) -- [CartItemDeletedListener.php:24-40](file://Listeners/CartItemDeletedListener.php#L24-L40) -- [InvoicePaidListener.php:58-125](file://Listeners/InvoicePaidListener.php#L58-L125) -- [AlertService.php:218-247](file://Services/AlertService.php#L218-L247) -- [CartItemDeletedListenerTest.php:21-125](file://tests/Unit/CartItemDeletedListenerTest.php#L21-L125) -- [InvoicePaidListenerTest.php:25-101](file://tests/Unit/InvoicePaidListenerTest.php#L25-L101) +- [CartItemCreatedListener.php:79-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L79-L86) +- [CartItemDeletedListener.php:24-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemDeletedListener.php#L24-L40) +- [InvoicePaidListener.php:58-125](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php#L58-L125) +- [AlertService.php:218-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L218-L247) +- [CartItemDeletedListenerTest.php:21-125](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/CartItemDeletedListenerTest.php#L21-L125) +- [InvoicePaidListenerTest.php:25-101](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/InvoicePaidListenerTest.php#L25-L101) ## Conclusion The extension leverages Paymenter’s event system to provide a robust reservation workflow tied to cart and checkout lifecycle events. It ensures resource availability through real-time checks, safeguards against race conditions with pessimistic locking and idempotency, and provides comprehensive alerting and observability. The AlertDeliveryFailed event enables extensibility for custom failure handling. Together, these mechanisms deliver a reliable and auditable reservation system integrated seamlessly into Paymenter. @@ -358,5 +376,5 @@ Example steps: - Add tests to validate behavior and error paths **Section sources** -- [DynamicPterodactyl.php:132-145](file://DynamicPterodactyl.php#L132-L145) -- [AlertDeliveryFailed.php:9-16](file://Events/AlertDeliveryFailed.php#L9-L16) \ No newline at end of file +- [DynamicPterodactyl.php:132-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L132-L145) +- [AlertDeliveryFailed.php:9-16](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L16) diff --git a/.qoder/repowiki/en/content/Getting Started.md b/.qoder/repowiki/en/content/Getting Started.md index 05f33c0..1913c00 100644 --- a/.qoder/repowiki/en/content/Getting Started.md +++ b/.qoder/repowiki/en/content/Getting Started.md @@ -1,18 +1,34 @@ # Getting Started +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + +## Current Setup Path + +Install the DynamicPterodactyl extension and its matching Paymenter companion as +one reviewed release. Run migrations before booting the extension, configure the +panel URL and application key, define per-node capacity policies, confirm +exclusive provisioning control, and use the setup wizard to create native +Paymenter dynamic-slider options. Do not deploy either side independently. + +Use the product resource-quote endpoint for checkout previews; reservations are +created by Paymenter cart events, not by a public reservation API. + +[[Architecture Overview|Architecture-Overview]] + + **Referenced Files in This Document** -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [routes/api.php](file://routes/api.php) -- [Admin/Pages/SetupWizard.php](file://Admin/Pages/SetupWizard.php) -- [Services/ConfigOptionSetupService.php](file://Services/ConfigOptionSetupService.php) -- [Services/SliderConfigReaderService.php](file://Services/SliderConfigReaderService.php) -- [Listeners/CartItemCreatedListener.php](file://Listeners/CartItemCreatedListener.php) -- [Http/Controllers/Api/AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) -- [Services/ReservationService.php](file://Services/ReservationService.php) -- [Models/ResourceReservation.php](file://Models/ResourceReservation.php) -- [AGENTS.md](file://AGENTS.md) -- [DECISIONS.md](file://DECISIONS.md) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [Admin/Pages/SetupWizard.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php) +- [Services/ConfigOptionSetupService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php) +- [Services/SliderConfigReaderService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php) +- [Http/Controllers/Api/AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [Models/ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [AGENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/AGENTS.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md) ## Table of Contents @@ -37,9 +53,9 @@ Key behaviors: - Customer-facing endpoints return only aggregate capacity per location; node-level details are admin-only. **Section sources** -- [DynamicPterodactyl.php:25-75](file://DynamicPterodactyl.php#L25-L75) -- [AGENTS.md:7-11](file://AGENTS.md#L7-L11) -- [DECISIONS.md:28-45](file://DECISIONS.md#L28-L45) +- [DynamicPterodactyl.php:25-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L25-L75) +- [AGENTS.md:7-11](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/AGENTS.md#L7-L11) +- [DECISIONS.md:28-45](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L28-L45) ## Project Structure The extension lives under Paymenter as an “Other” extension and integrates via its boot process. It registers routes, policies, listeners, and scheduled tasks that tie into Paymenter’s cart and invoice lifecycle. @@ -54,12 +70,12 @@ A --> F["Scheduled jobs
cleanup expired reservations every minute
check ``` **Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [routes/api.php:17-40](file://routes/api.php#L17-L40) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [routes/api.php:17-40](file://routes/api.php#L17-L40) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ## Core Components - Extension entrypoint: loads routes, policies, observers, event listeners, and schedules. @@ -70,13 +86,13 @@ A --> F["Scheduled jobs
cleanup expired reservations every minute
check - Listeners: bridge Paymenter events (cart/invoice/service) into reservation actions. **Section sources** -- [DynamicPterodactyl.php:45-127](file://DynamicPterodactyl.php#L45-L127) -- [Admin/Pages/SetupWizard.php:26-75](file://Admin/Pages/SetupWizard.php#L26-L75) -- [Services/ConfigOptionSetupService.php:44-77](file://Services/ConfigOptionSetupService.php#L44-L77) -- [Services/SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) -- [Http/Controllers/Api/AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Listeners/CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) +- [DynamicPterodactyl.php:45-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L45-L127) +- [Admin/Pages/SetupWizard.php:26-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L26-L75) +- [Services/ConfigOptionSetupService.php:44-77](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L77) +- [Services/SliderConfigReaderService.php:14-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L53) +- [Http/Controllers/Api/AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [Services/ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [Listeners/CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) ## Architecture Overview This extension complements the built-in Pterodactyl server extension. It does not provision servers itself; it ensures resources are available and reserved while customers complete checkout. @@ -101,9 +117,9 @@ Ext-->>Paymenter : Link reservation to service ``` **Diagram sources** -- [Listeners/CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [DynamicPterodactyl.php:106-145](file://DynamicPterodactyl.php#L106-L145) +- [Listeners/CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [Services/ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [DynamicPterodactyl.php:106-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L106-L145) ## Detailed Component Analysis @@ -117,8 +133,8 @@ Ext-->>Paymenter : Link reservation to service These settings are exposed through the extension’s configuration UI and used by services to connect to Pterodactyl and manage reservation lifetimes. **Section sources** -- [DynamicPterodactyl.php:48-75](file://DynamicPterodactyl.php#L48-L75) -- [DynamicPterodactyl.php:78-91](file://DynamicPterodactyl.php#L78-L91) +- [DynamicPterodactyl.php:48-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L48-L75) +- [DynamicPterodactyl.php:78-91](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L78-L91) ### Initial Setup: Creating Dynamic Sliders Use the Filament-based Setup Wizard to add RAM, CPU, and Disk sliders to a product: @@ -129,9 +145,9 @@ Use the Filament-based Setup Wizard to add RAM, CPU, and Disk sliders to a produ The wizard writes native dynamic_slider ConfigOptions to Paymenter core. These options drive both the frontend sliders and pricing calculations. **Section sources** -- [Admin/Pages/SetupWizard.php:26-75](file://Admin/Pages/SetupWizard.php#L26-L75) -- [Services/ConfigOptionSetupService.php:44-77](file://Services/ConfigOptionSetupService.php#L44-L77) -- [Services/ConfigOptionSetupService.php:117-171](file://Services/ConfigOptionSetupService.php#L117-L171) +- [Admin/Pages/SetupWizard.php:26-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L26-L75) +- [Services/ConfigOptionSetupService.php:44-77](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L77) +- [Services/ConfigOptionSetupService.php:117-171](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L117-L171) ### Quick Start: Verify the Extension Is Working - Ensure Pterodactyl credentials are configured in the extension settings. @@ -147,9 +163,9 @@ Relevant endpoints: - GET /api/dynamic-pterodactyl/pricing/config/{productId} **Section sources** -- [routes/api.php:17-40](file://routes/api.php#L17-L40) -- [Http/Controllers/Api/AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [Listeners/CartItemCreatedListener.php:47-87](file://Listeners/CartItemCreatedListener.php#L47-L87) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [Http/Controllers/Api/AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [Listeners/CartItemCreatedListener.php:47-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L47-L87) ### How Reservations Work - Creation: When a cart item with dynamic sliders is added, the extension reads slider values, selects a best-fit node from live availability, and creates a pending reservation with a TTL. @@ -174,14 +190,14 @@ Expire --> EndExpired["Released back to pool"] ``` **Diagram sources** -- [Listeners/CartItemCreatedListener.php:13-87](file://Listeners/CartItemCreatedListener.php#L13-L87) -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Services/ReservationService.php:384-405](file://Services/ReservationService.php#L384-L405) +- [Listeners/CartItemCreatedListener.php:13-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L13-L87) +- [Services/ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [Services/ReservationService.php:384-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L384-L405) **Section sources** -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Services/ReservationService.php:384-405](file://Services/ReservationService.php#L384-L405) -- [Models/ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) +- [Services/ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [Services/ReservationService.php:384-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L384-L405) +- [Models/ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) ### Relationship to Paymenter’s Built-in Pterodactyl Server Extension - This extension is a companion enhancement. It handles dynamic sliders, availability, and reservations. @@ -189,8 +205,8 @@ Expire --> EndExpired["Released back to pool"] - If this extension fails, the product still works without sliders (graceful degradation). **Section sources** -- [DynamicPterodactyl.php:33-40](file://DynamicPterodactyl.php#L33-L40) -- [DECISIONS.md:9-25](file://DECISIONS.md#L9-L25) +- [DynamicPterodactyl.php:33-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L33-L40) +- [DECISIONS.md:9-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DECISIONS.md#L9-L25) ## Dependency Analysis ```mermaid @@ -208,16 +224,16 @@ SliderCfg["SliderConfigReaderService"] --> ConfigOpt["ConfigOption (dynamic_slid ``` **Diagram sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [routes/api.php:17-40](file://routes/api.php#L17-L40) -- [Http/Controllers/Api/AvailabilityController.php:11-20](file://Http/Controllers/Api/AvailabilityController.php#L11-L20) -- [Admin/Pages/SetupWizard.php:26-75](file://Admin/Pages/SetupWizard.php#L26-L75) -- [Services/ConfigOptionSetupService.php:44-77](file://Services/ConfigOptionSetupService.php#L44-L77) -- [Services/SliderConfigReaderService.php:14-53](file://Services/SliderConfigReaderService.php#L14-L53) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [Http/Controllers/Api/AvailabilityController.php:11-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L11-L20) +- [Admin/Pages/SetupWizard.php:26-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L26-L75) +- [Services/ConfigOptionSetupService.php:44-77](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L44-L77) +- [Services/SliderConfigReaderService.php:14-53](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php#L14-L53) **Section sources** -- [DynamicPterodactyl.php:96-145](file://DynamicPterodactyl.php#L96-L145) -- [routes/api.php:17-40](file://routes/api.php#L17-L40) +- [DynamicPterodactyl.php:96-145](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L145) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ## Performance Considerations - Real-time availability: Pterodactyl API responses are never cached; availability is always fresh. Batch calls are used to reduce overhead. @@ -244,11 +260,11 @@ Where to look: - Logs: Listener errors when creating reservations. **Section sources** -- [DynamicPterodactyl.php:48-75](file://DynamicPterodactyl.php#L48-L75) -- [Admin/Pages/SetupWizard.php:26-75](file://Admin/Pages/SetupWizard.php#L26-L75) -- [Http/Controllers/Api/AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [Listeners/CartItemCreatedListener.php:79-87](file://Listeners/CartItemCreatedListener.php#L79-L87) -- [Services/ReservationService.php:384-405](file://Services/ReservationService.php#L384-L405) +- [DynamicPterodactyl.php:48-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L48-L75) +- [Admin/Pages/SetupWizard.php:26-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L26-L75) +- [Http/Controllers/Api/AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [Listeners/CartItemCreatedListener.php:79-87](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php#L79-L87) +- [Services/ReservationService.php:384-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L384-L405) ## Conclusion The Dynamic Pterodactyl extension enhances your Pterodactyl products with dynamic RAM/CPU/Disk sliders, real-time availability checks, and short-lived reservations to prevent overselling during checkout. It integrates seamlessly with Paymenter’s built-in Pterodactyl server extension, leaving provisioning to the core while focusing on availability and reservation management. Use the Setup Wizard to configure sliders, verify availability via the API, and rely on automatic reservation lifecycle handling during the cart-to-payment flow. @@ -274,4 +290,4 @@ The Dynamic Pterodactyl extension enhances your Pterodactyl products with dynami - GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes **Section sources** -- [routes/api.php:17-40](file://routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 2247f18..897ff8d 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -1,21 +1,39 @@ # Testing +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + +## Current Test Contract + +The cross-repository workflow checks PHP 8.3 and 8.4 against SQLite and MariaDB +11/12, lints every changed PHP file, runs the full extension suite, exercises the +Paymenter provisioning seam, checks formatting, and audits the pinned companion +lock file for security advisories. + +Standalone SQLite tests must use `DB_DATABASE=:temporary:`. The guard claims a +process-private named-memory database and rejects inherited generated URIs in +child processes. MySQL/MariaDB tests may use only the explicitly named +`paymenter_test` database while `APP_ENV=testing`. + +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/TestDatabaseGuard.php) + + **Referenced Files in This Document** -- [phpunit.xml](file://phpunit.xml) -- [tests/bootstrap.php](file://tests/bootstrap.php) -- [tests/TestCase.php](file://tests/TestCase.php) -- [tests/LaravelTestCase.php](file://tests/LaravelTestCase.php) -- [Services/ReservationService.php](file://Services/ReservationService.php) -- [Services/ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [Services/AlertService.php](file://Services/AlertService.php) -- [Models/ResourceReservation.php](file://Models/ResourceReservation.php) -- [Models/AlertConfig.php](file://Models/AlertConfig.php) -- [tests/Unit/ReservationServiceTest.php](file://tests/Unit/ReservationServiceTest.php) -- [tests/Unit/ResourceCalculationServiceTest.php](file://tests/Unit/ResourceCalculationServiceTest.php) -- [tests/Unit/AlertServiceTest.php](file://tests/Unit/AlertServiceTest.php) -- [tests/Feature/ReservationApiTest.php](file://tests/Feature/ReservationApiTest.php) -- [tests/Feature/AvailabilityApiTest.php](file://tests/Feature/AvailabilityApiTest.php) +- [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php) +- [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) +- [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [Services/AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) +- [Models/ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [Models/AlertConfig.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php) +- [tests/Unit/ReservationServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php) +- [tests/Unit/ResourceCalculationServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php) +- [tests/Unit/AlertServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php) +- [tests/Feature/ReservationApiTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php) +- [tests/Feature/AvailabilityApiTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AvailabilityApiTest.php) ## Table of Contents @@ -67,21 +85,21 @@ U --> AC ``` **Diagram sources** -- [phpunit.xml:1-43](file://phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](file://tests/bootstrap.php#L1-L21) -- [tests/TestCase.php:1-63](file://tests/TestCase.php#L1-L63) -- [tests/LaravelTestCase.php:1-183](file://tests/LaravelTestCase.php#L1-L183) -- [Services/ReservationService.php:1-453](file://Services/ReservationService.php#L1-L453) -- [Services/ResourceCalculationService.php:1-545](file://Services/ResourceCalculationService.php#L1-L545) -- [Services/AlertService.php:1-392](file://Services/AlertService.php#L1-L392) -- [Models/ResourceReservation.php:1-65](file://Models/ResourceReservation.php#L1-L65) -- [Models/AlertConfig.php:1-56](file://Models/AlertConfig.php#L1-L56) +- [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php#L1-L21) +- [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) +- [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) +- [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) +- [Services/ResourceCalculationService.php:1-545](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L1-L545) +- [Services/AlertService.php:1-392](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L1-L392) +- [Models/ResourceReservation.php:1-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L1-L65) +- [Models/AlertConfig.php:1-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L1-L56) **Section sources** -- [phpunit.xml:1-43](file://phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](file://tests/bootstrap.php#L1-L21) -- [tests/TestCase.php:1-63](file://tests/TestCase.php#L1-L63) -- [tests/LaravelTestCase.php:1-183](file://tests/LaravelTestCase.php#L1-L183) +- [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php#L1-L21) +- [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) +- [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) ## Core Components Key components under test: @@ -91,11 +109,11 @@ Key components under test: - Models: ResourceReservation and AlertConfig define data contracts and scopes used by services. **Section sources** -- [Services/ReservationService.php:1-453](file://Services/ReservationService.php#L1-L453) -- [Services/ResourceCalculationService.php:1-545](file://Services/ResourceCalculationService.php#L1-L545) -- [Services/AlertService.php:1-392](file://Services/AlertService.php#L1-L392) -- [Models/ResourceReservation.php:1-65](file://Models/ResourceReservation.php#L1-L65) -- [Models/AlertConfig.php:1-56](file://Models/AlertConfig.php#L1-L56) +- [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) +- [Services/ResourceCalculationService.php:1-545](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L1-L545) +- [Services/AlertService.php:1-392](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L1-L392) +- [Models/ResourceReservation.php:1-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L1-L65) +- [Models/AlertConfig.php:1-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L1-L56) ## Architecture Overview The testing architecture isolates external dependencies and enforces deterministic environments: @@ -123,9 +141,9 @@ sequenceDiagram ``` **Diagram sources** -- [phpunit.xml:28-41](file://phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](file://tests/bootstrap.php#L23-L48) -- [tests/LaravelTestCase.php:13-25](file://tests/LaravelTestCase.php#L13-L25) +- [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php#L23-L48) +- [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -155,8 +173,8 @@ Present --> End(["Array result"]) ``` **Diagram sources** -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Services/ReservationService.php:407-452](file://Services/ReservationService.php#L407-L452) +- [Services/ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [Services/ReservationService.php:407-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L407-L452) Key test patterns: - Mock DB facade chains for confirm/cancel/extend to assert status transitions and audit calls. @@ -170,10 +188,10 @@ Example references: - CleanupExpired marking pending rows as expired and auditing batch count. **Section sources** -- [tests/Unit/ReservationServiceTest.php:1-800](file://tests/Unit/ReservationServiceTest.php#L1-L800) -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [Services/ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) -- [Services/ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) +- [tests/Unit/ReservationServiceTest.php:1-800](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L1-L800) +- [Services/ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [Services/ReservationService.php:166-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L281) +- [Services/ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) ### Resource Calculation Service Tests Focus areas: @@ -199,9 +217,9 @@ RCS-->>T : Availability with max_available and totals ``` **Diagram sources** -- [Services/ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [Services/ResourceCalculationService.php:226-245](file://Services/ResourceCalculationService.php#L226-L245) -- [Services/ResourceCalculationService.php:500-522](file://Services/ResourceCalculationService.php#L500-L522) +- [Services/ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [Services/ResourceCalculationService.php:226-245](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L226-L245) +- [Services/ResourceCalculationService.php:500-522](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L500-L522) Key test patterns: - Http::preventStrayRequests() to ensure no stray network calls. @@ -210,10 +228,10 @@ Key test patterns: - Validate sanitized error messages that do not leak internal hostnames. **Section sources** -- [tests/Unit/ResourceCalculationServiceTest.php:1-469](file://tests/Unit/ResourceCalculationServiceTest.php#L1-L469) -- [Services/ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) -- [Services/ResourceCalculationService.php:291-384](file://Services/ResourceCalculationService.php#L291-L384) -- [Services/ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [tests/Unit/ResourceCalculationServiceTest.php:1-469](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L1-L469) +- [Services/ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) +- [Services/ResourceCalculationService.php:291-384](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L291-L384) +- [Services/ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) ### Alert Service Tests Focus areas: @@ -240,9 +258,9 @@ NextCfg --> |done| AEnd(["Done"]) ``` **Diagram sources** -- [Services/AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [Services/AlertService.php:77-126](file://Services/AlertService.php#L77-L126) -- [Services/AlertService.php:128-248](file://Services/AlertService.php#L128-L248) +- [Services/AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [Services/AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) +- [Services/AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) Key test patterns: - Isolate Facade application using a minimal container to avoid side effects. @@ -251,9 +269,9 @@ Key test patterns: - Assert AlertDeliveryFailed event dispatch when all channels fail. **Section sources** -- [tests/Unit/AlertServiceTest.php:1-770](file://tests/Unit/AlertServiceTest.php#L1-L770) -- [Services/AlertService.php:33-248](file://Services/AlertService.php#L33-L248) -- [Models/AlertConfig.php:1-56](file://Models/AlertConfig.php#L1-L56) +- [tests/Unit/AlertServiceTest.php:1-770](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L1-L770) +- [Services/AlertService.php:33-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L248) +- [Models/AlertConfig.php:1-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L1-L56) ### Feature Tests for API Endpoints Focus areas: @@ -281,8 +299,8 @@ Ctrl-->>C : 200 OK {success : true, data} ``` **Diagram sources** -- [tests/Feature/ReservationApiTest.php:37-78](file://tests/Feature/ReservationApiTest.php#L37-L78) -- [Services/ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [tests/Feature/ReservationApiTest.php:37-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L37-L78) +- [Services/ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) Key test patterns: - Require routes/api.php before making requests. @@ -291,8 +309,8 @@ Key test patterns: - Assert throttling behavior at both guest IP and user levels. **Section sources** -- [tests/Feature/ReservationApiTest.php:1-490](file://tests/Feature/ReservationApiTest.php#L1-L490) -- [tests/Feature/AvailabilityApiTest.php:1-95](file://tests/Feature/AvailabilityApiTest.php#L1-L95) +- [tests/Feature/ReservationApiTest.php:1-490](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L1-L490) +- [tests/Feature/AvailabilityApiTest.php:1-95](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AvailabilityApiTest.php#L1-L95) ## Dependency Analysis Coupling and isolation: @@ -312,14 +330,14 @@ ALS --> NOTIF["Notifications"] ``` **Diagram sources** -- [Services/ReservationService.php:20-35](file://Services/ReservationService.php#L20-L35) -- [Services/ResourceCalculationService.php:12-21](file://Services/ResourceCalculationService.php#L12-L21) -- [Services/AlertService.php:23-28](file://Services/AlertService.php#L23-L28) +- [Services/ReservationService.php:20-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L20-L35) +- [Services/ResourceCalculationService.php:12-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L12-L21) +- [Services/AlertService.php:23-28](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L23-L28) **Section sources** -- [Services/ReservationService.php:20-35](file://Services/ReservationService.php#L20-L35) -- [Services/ResourceCalculationService.php:12-21](file://Services/ResourceCalculationService.php#L12-L21) -- [Services/AlertService.php:23-28](file://Services/AlertService.php#L23-L28) +- [Services/ReservationService.php:20-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L20-L35) +- [Services/ResourceCalculationService.php:12-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L12-L21) +- [Services/AlertService.php:23-28](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L23-L28) ## Performance Considerations - Keep tests fast by avoiding real network calls; always use Http::fake() for Pterodactyl endpoints. @@ -343,10 +361,10 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](file://tests/bootstrap.php#L23-L48) -- [tests/Unit/ResourceCalculationServiceTest.php:18-33](file://tests/Unit/ResourceCalculationServiceTest.php#L18-L33) -- [tests/Unit/AlertServiceTest.php:26-62](file://tests/Unit/AlertServiceTest.php#L26-L62) -- [tests/Unit/ReservationServiceTest.php:29-46](file://tests/Unit/ReservationServiceTest.php#L29-L46) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php#L23-L48) +- [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) +- [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) +- [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) ## Conclusion The test suite provides robust coverage across service logic, API endpoints, and alerting workflows. By enforcing strict isolation through array cache/session/queue, sync queue, and guarded database settings, tests remain deterministic and fast. Mocking and faking external dependencies ensures reliability while validating critical behaviors like idempotency, authorization, and error handling. @@ -363,9 +381,9 @@ The test suite provides robust coverage across service logic, API endpoints, and - Run all tests: vendor/bin/phpunit **Section sources** -- [phpunit.xml:13-20](file://phpunit.xml#L13-L20) -- [phpunit.xml:28-41](file://phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](file://tests/bootstrap.php#L23-L48) +- [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) +- [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -378,9 +396,9 @@ The test suite provides robust coverage across service logic, API endpoints, and - Assert response codes, JSON structure, and database state. **Section sources** -- [tests/LaravelTestCase.php:13-25](file://tests/LaravelTestCase.php#L13-L25) -- [tests/Feature/ReservationApiTest.php:22-35](file://tests/Feature/ReservationApiTest.php#L22-L35) -- [tests/Unit/ReservationServiceTest.php:52-67](file://tests/Unit/ReservationServiceTest.php#L52-L67) +- [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) +- [tests/Feature/ReservationApiTest.php:22-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L22-L35) +- [tests/Unit/ReservationServiceTest.php:52-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L52-L67) ### Mocking External Dependencies - Pterodactyl API: @@ -393,9 +411,9 @@ The test suite provides robust coverage across service logic, API endpoints, and - Use Notification::fake() and Event::fake() to assert deliveries and event dispatches. **Section sources** -- [tests/Unit/ResourceCalculationServiceTest.php:35-51](file://tests/Unit/ResourceCalculationServiceTest.php#L35-L51) -- [tests/Unit/ResourceCalculationServiceTest.php:86-123](file://tests/Unit/ResourceCalculationServiceTest.php#L86-L123) -- [tests/Unit/AlertServiceTest.php:87-126](file://tests/Unit/AlertServiceTest.php#L87-L126) +- [tests/Unit/ResourceCalculationServiceTest.php:35-51](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L35-L51) +- [tests/Unit/ResourceCalculationServiceTest.php:86-123](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L86-L123) +- [tests/Unit/AlertServiceTest.php:87-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L87-L126) ### Test Database Setup and Fixtures - Database isolation: @@ -406,9 +424,9 @@ The test suite provides robust coverage across service logic, API endpoints, and - Use factories where available; otherwise insert raw rows via DB facade. **Section sources** -- [phpunit.xml:34-36](file://phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](file://tests/bootstrap.php#L23-L48) -- [tests/Feature/ReservationApiTest.php:402-446](file://tests/Feature/ReservationApiTest.php#L402-L446) +- [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php#L23-L48) +- [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns - Response assertions: @@ -421,9 +439,9 @@ The test suite provides robust coverage across service logic, API endpoints, and - Http::assertSentCount(), Http::assertNotSent(). **Section sources** -- [tests/Feature/ReservationApiTest.php:37-78](file://tests/Feature/ReservationApiTest.php#L37-L78) -- [tests/Unit/AlertServiceTest.php:484-527](file://tests/Unit/AlertServiceTest.php#L484-L527) -- [tests/Unit/ResourceCalculationServiceTest.php:35-51](file://tests/Unit/ResourceCalculationServiceTest.php#L35-L51) +- [tests/Feature/ReservationApiTest.php:37-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L37-L78) +- [tests/Unit/AlertServiceTest.php:484-527](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L484-L527) +- [tests/Unit/ResourceCalculationServiceTest.php:35-51](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L35-L51) ### Examples: Reservation Workflows, Availability Calculations, Alert Systems - Reservation workflow: @@ -439,11 +457,11 @@ The test suite provides robust coverage across service logic, API endpoints, and - Send emails/webhooks; record delivery logs; emit failure events when all channels fail. **Section sources** -- [tests/Feature/ReservationApiTest.php:37-78](file://tests/Feature/ReservationApiTest.php#L37-L78) -- [tests/Unit/ReservationServiceTest.php:509-550](file://tests/Unit/ReservationServiceTest.php#L509-L550) -- [tests/Unit/ResourceCalculationServiceTest.php:162-193](file://tests/Unit/ResourceCalculationServiceTest.php#L162-L193) -- [tests/Unit/ResourceCalculationServiceTest.php:195-252](file://tests/Unit/ResourceCalculationServiceTest.php#L195-L252) -- [tests/Unit/AlertServiceTest.php:484-527](file://tests/Unit/AlertServiceTest.php#L484-L527) +- [tests/Feature/ReservationApiTest.php:37-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L37-L78) +- [tests/Unit/ReservationServiceTest.php:509-550](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L509-L550) +- [tests/Unit/ResourceCalculationServiceTest.php:162-193](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L162-L193) +- [tests/Unit/ResourceCalculationServiceTest.php:195-252](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L195-L252) +- [tests/Unit/AlertServiceTest.php:484-527](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L484-L527) ### Debugging Techniques - Enable verbose output: vendor/bin/phpunit --verbose @@ -452,8 +470,8 @@ The test suite provides robust coverage across service logic, API endpoints, and - Isolate failing tests with --filter to reduce noise. **Section sources** -- [phpunit.xml:5-12](file://phpunit.xml#L5-L12) -- [tests/Unit/AlertServiceTest.php:26-62](file://tests/Unit/AlertServiceTest.php#L26-L62) +- [phpunit.xml:5-12](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L5-L12) +- [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) ### Performance Profiling Approaches - Measure test execution time with --testdox or CI timing reports. diff --git a/.qoder/repowiki/en/content/Troubleshooting.md b/.qoder/repowiki/en/content/Troubleshooting.md index f6867ed..b932ae7 100644 --- a/.qoder/repowiki/en/content/Troubleshooting.md +++ b/.qoder/repowiki/en/content/Troubleshooting.md @@ -1,19 +1,22 @@ # Troubleshooting +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, or API shapes are historical. + + **Referenced Files in This Document** -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [api.php](file://routes/api.php) -- [AvailabilityController.php](file://Http/Controllers/Api/AvailabilityController.php) -- [ReservationController.php](file://Http/Controllers/Api/ReservationController.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [NodeSelectionService.php](file://Services/NodeSelectionService.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [CartItemCreatedListener.php](file://Listeners/CartItemCreatedListener.php) -- [InvoicePaidListener.php](file://Listeners/InvoicePaidListener.php) -- [AlertService.php](file://Services/AlertService.php) -- [AuditsExtensionActions.php](file://Services/Concerns/AuditsExtensionActions.php) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php) +- [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) +- [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [NodeSelectionService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/CartItemCreatedListener.php) +- [InvoicePaidListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Listeners/InvoicePaidListener.php) +- [AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) +- [AuditsExtensionActions.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) ## Table of Contents @@ -55,17 +58,17 @@ Listeners --> ResSvc ``` **Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [api.php:17-40](file://routes/api.php#L17-L40) -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [ResourceCalculationService.php:26-222](file://Services/ResourceCalculationService.php#L26-L222) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [ResourceCalculationService.php:26-222](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L222) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [api.php:17-40](file://routes/api.php#L17-L40) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ## Core Components - AvailabilityController exposes per-location availability and node details, returning only aggregate capacity to customers. @@ -76,12 +79,12 @@ Listeners --> ResSvc - AlertService periodically evaluates capacity thresholds and sends notifications via email or webhooks, logging delivery outcomes. **Section sources** -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [ReservationController.php:24-136](file://Http/Controllers/Api/ReservationController.php#L24-L136) -- [ResourceCalculationService.php:26-222](file://Services/ResourceCalculationService.php#L26-L222) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [ReservationController.php:24-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L136) +- [ResourceCalculationService.php:26-222](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L222) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) ## Architecture Overview The system enforces real-time availability by querying Pterodactyl on each request without caching. Reservations protect capacity during checkout using database transactions with pessimistic locks and retries on deadlock. Alerts run on schedules to monitor utilization and notify administrators. @@ -106,10 +109,10 @@ A-->>C : {success,data} ``` **Diagram sources** -- [api.php:17-22](file://routes/api.php#L17-L22) -- [AvailabilityController.php:22-52](file://Http/Controllers/Api/AvailabilityController.php#L22-L52) -- [NodeSelectionService.php:81-86](file://Services/NodeSelectionService.php#L81-L86) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L22) +- [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) +- [NodeSelectionService.php:81-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L81-L86) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) ## Detailed Component Analysis @@ -147,12 +150,12 @@ Err --> End ``` **Diagram sources** -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) **Section sources** -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [api.php:17-40](file://routes/api.php#L17-L40) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ### Rate Limiting Responses (HTTP 429) Symptoms: @@ -169,8 +172,8 @@ Resolution steps: - Monitor logs for repeated 429 occurrences and investigate upstream load. **Section sources** -- [ResourceCalculationService.php:473-475](file://Services/ResourceCalculationService.php#L473-L475) -- [api.php:17-40](file://routes/api.php#L17-L40) +- [ResourceCalculationService.php:473-475](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L473-L475) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ### Reservation Conflicts and Idempotency Symptoms: @@ -210,12 +213,12 @@ RS->>DB : COMMIT ``` **Diagram sources** -- [ReservationController.php:24-60](file://Http/Controllers/Api/ReservationController.php#L24-L60) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) +- [ReservationController.php:24-60](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L60) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:431-452](file://Services/ReservationService.php#L431-L452) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:431-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L431-L452) ### Database Locking and Deadlocks Symptoms: @@ -232,9 +235,9 @@ Resolution steps: - Monitor database metrics for lock waits and adjust workload accordingly. **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:444-452](file://Services/ReservationService.php#L444-L452) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:55-61](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L55-L61) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:444-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L444-L452) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:55-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L55-L61) ### Timeout Issues Symptoms: @@ -251,7 +254,7 @@ Resolution steps: - Review logs for repeated connection exceptions and address infrastructure issues. **Section sources** -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) ### Availability Discrepancies Symptoms: @@ -267,8 +270,8 @@ Resolution steps: - Validate that nodes are not in maintenance mode and that pending reservations are accounted for. **Section sources** -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) ### Reservation Expiration Behavior Symptoms: @@ -285,9 +288,9 @@ Resolution steps: - Monitor scheduled jobs to ensure they run every minute. **Section sources** -- [DynamicPterodactyl.php:116-121](file://DynamicPterodactyl.php#L116-L121) -- [ReservationService.php:385-405](file://Services/ReservationService.php#L385-L405) -- [ReservationController.php:102-136](file://Http/Controllers/Api/ReservationController.php#L102-L136) +- [DynamicPterodactyl.php:116-121](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L116-L121) +- [ReservationService.php:385-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L385-L405) +- [ReservationController.php:102-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L102-L136) ### Alert Configuration Problems Symptoms: @@ -304,9 +307,9 @@ Resolution steps: - Inspect alert delivery logs for channel-specific errors. **Section sources** -- [DynamicPterodactyl.php:123-126](file://DynamicPterodactyl.php#L123-L126) -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) +- [DynamicPterodactyl.php:123-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L123-L126) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) ## Dependency Analysis The extension’s runtime depends on: @@ -324,12 +327,12 @@ Core --> Schedule["Scheduler"] ``` **Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [api.php:17-40](file://routes/api.php#L17-L40) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [api.php:17-40](file://routes/api.php#L17-L40) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ## Performance Considerations - Avoid caching Pterodactyl responses; rely on real-time queries for accuracy. @@ -352,9 +355,9 @@ Diagnostics: - Confirm route throttling is not rejecting requests prematurely. **Section sources** -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) -- [api.php:17-40](file://routes/api.php#L17-L40) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ### Authentication Failures Steps: @@ -367,8 +370,8 @@ Diagnostics: - Check for malformed headers or incorrect base URL formatting. **Section sources** -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) ### Rate Limiting Responses Steps: @@ -381,8 +384,8 @@ Diagnostics: - Evaluate whether batched operations can reduce total requests. **Section sources** -- [ResourceCalculationService.php:473-475](file://Services/ResourceCalculationService.php#L473-L475) -- [api.php:17-40](file://routes/api.php#L17-L40) +- [ResourceCalculationService.php:473-475](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L473-L475) +- [api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/routes/api.php#L17-L40) ### Reservation Conflicts Steps: @@ -395,8 +398,8 @@ Diagnostics: - Confirm pending reservation locks are functioning under load. **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:431-452](file://Services/ReservationService.php#L431-L452) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:431-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L431-L452) ### Database Locking Deadlocks Steps: @@ -409,8 +412,8 @@ Diagnostics: - Audit long-running queries and external processes holding locks. **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:444-452](file://Services/ReservationService.php#L444-L452) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:444-452](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L444-L452) ### Timeout Issues Steps: @@ -423,7 +426,7 @@ Diagnostics: - Measure end-to-end request durations to pinpoint bottlenecks. **Section sources** -- [ResourceCalculationService.php:452-498](file://Services/ResourceCalculationService.php#L452-L498) +- [ResourceCalculationService.php:452-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L452-L498) ### Availability Discrepancies Steps: @@ -436,8 +439,8 @@ Diagnostics: - Review logs for node selection decisions and scoring. **Section sources** -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [NodeSelectionService.php:22-86](file://Services/NodeSelectionService.php#L22-L86) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [NodeSelectionService.php:22-86](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/NodeSelectionService.php#L22-L86) ### Reservation Expiration Behavior Steps: @@ -450,9 +453,9 @@ Diagnostics: - Review logs for cleanup runs and expired batch updates. **Section sources** -- [DynamicPterodactyl.php:116-121](file://DynamicPterodactyl.php#L116-L121) -- [ReservationService.php:385-405](file://Services/ReservationService.php#L385-L405) -- [ReservationController.php:102-136](file://Http/Controllers/Api/ReservationController.php#L102-L136) +- [DynamicPterodactyl.php:116-121](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L116-L121) +- [ReservationService.php:385-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L385-L405) +- [ReservationController.php:102-136](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L102-L136) ### Alert Configuration Problems Steps: @@ -465,9 +468,9 @@ Diagnostics: - Review logs for webhook and email delivery errors. **Section sources** -- [DynamicPterodactyl.php:123-126](file://DynamicPterodactyl.php#L123-L126) -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) +- [DynamicPterodactyl.php:123-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L123-L126) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) ### Log Analysis Techniques - Focus on logs from controllers, services, and listeners for error contexts. @@ -475,10 +478,10 @@ Diagnostics: - Correlate timestamps across routes, services, and database operations. **Section sources** -- [AvailabilityController.php:45-52](file://Http/Controllers/Api/AvailabilityController.php#L45-L52) -- [ReservationController.php:49-59](file://Http/Controllers/Api/ReservationController.php#L49-L59) -- [ResourceCalculationService.php:473-498](file://Services/ResourceCalculationService.php#L473-L498) -- [AuditsExtensionActions.php:10-32](file://Services/Concerns/AuditsExtensionActions.php#L10-L32) +- [AvailabilityController.php:45-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L45-L52) +- [ReservationController.php:49-59](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L49-L59) +- [ResourceCalculationService.php:473-498](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L473-L498) +- [AuditsExtensionActions.php:10-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L32) ### Performance Profiling Approaches - Profile HTTP calls to Pterodactyl to identify slow endpoints. @@ -512,9 +515,9 @@ This guide consolidates diagnosis and resolution steps for common issues in the - Inspect alert delivery logs to diagnose notification failures. **Section sources** -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) -- [ReservationService.php:335-382](file://Services/ReservationService.php#L335-L382) -- [AlertService.php:304-323](file://Services/AlertService.php#L304-L323) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) +- [ReservationService.php:335-382](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L335-L382) +- [AlertService.php:304-323](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L304-L323) ### FAQ - Why does availability differ between customer and admin views? @@ -525,7 +528,7 @@ This guide consolidates diagnosis and resolution steps for common issues in the - Check alert configuration activity, thresholds, admin recipients, and delivery logs for channel-specific errors. **Section sources** -- [AvailabilityController.php:22-69](file://Http/Controllers/Api/AvailabilityController.php#L22-L69) -- [DynamicPterodactyl.php:116-126](file://DynamicPterodactyl.php#L116-L126) -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) +- [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) +- [DynamicPterodactyl.php:116-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L116-L126) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 768dcd8..29d0653 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"6b7f83bda6f7c3fe014d52428b31af1638daa6cc","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"0d0b6169aaef5f44f311f82bae05bbf4060e63c3","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file From 7ff4d47019cb9a26380b1d57bd9930dd8e29c93e Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 03:11:37 +1000 Subject: [PATCH 58/95] ci: pin workflow actions to verified commits --- .../workflows/cross-repository-integration.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml index 1f72961..4c4771f 100644 --- a/.github/workflows/cross-repository-integration.yml +++ b/.github/workflows/cross-repository-integration.yml @@ -25,21 +25,21 @@ jobs: steps: - name: Check out Dynamic Pterodactyl - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: path: dynamic-pterodactyl fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Check out companion Paymenter - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network ref: 4bab39fa1ee8ae471a104efda15dd1ac037f209e path: paymenter - name: Set up PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2 with: php-version: '8.3' extensions: bcmath, curl, gd, mbstring, mysql, openssl, pdo, tokenizer, xml, zip @@ -88,19 +88,19 @@ jobs: steps: - name: Check out Dynamic Pterodactyl - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: path: dynamic-pterodactyl - name: Check out companion Paymenter - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network ref: 4bab39fa1ee8ae471a104efda15dd1ac037f209e path: paymenter - name: Set up PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2 with: php-version: ${{ matrix.php }} extensions: bcmath, curl, gd, mbstring, mysql, openssl, pdo, pdo_sqlite, sqlite3, tokenizer, xml, zip @@ -190,19 +190,19 @@ jobs: steps: - name: Check out Dynamic Pterodactyl - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: path: dynamic-pterodactyl - name: Check out companion Paymenter - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network ref: 4bab39fa1ee8ae471a104efda15dd1ac037f209e path: paymenter - name: Set up PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2 with: php-version: ${{ matrix.php }} extensions: bcmath, curl, gd, mbstring, mysql, openssl, pdo, tokenizer, xml, zip From c33704fe9c768c86e67a941d03927b7c29983585 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 03:11:37 +1000 Subject: [PATCH 59/95] docs: close successor reconciliation checkpoint --- PROGRESS.md | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/PROGRESS.md b/PROGRESS.md index 7ed42cf..27d73fb 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -6,9 +6,9 @@ Active implementation tracking. **Claude: Update this as you work.** ## Current Status -**Phase**: Panel/GitHub reconciliation and Qoder Wiki refresh -**Last Updated**: 2026-08-17 -**Last Session**: Preserved the dp-20 close-out, reconciled the location availability batching work, hardened the standalone Windows test database guard, and refreshed the Qoder/GitHub Wiki documentation for the batched `locations/{id}?include=nodes,servers` flow. +**Phase**: PR #22 + PR #23 successor review and handoff +**Last Updated**: 2026-08-18 +**Last Session**: Fully rebased PR #22 onto the reviewed PR #23 work, restored every deployment protection, validated the exact extension/Paymenter pair across the full CI matrix and live read-only API path, and reconciled the preserved Qoder/GitHub Wiki. --- @@ -16,7 +16,7 @@ Active implementation tracking. **Claude: Update this as you work.** > **For Claude**: Read this + "Current Session State" to quickly understand where we are. -All dp-NN backlog items are implemented. The active reconciliation is staged on `agent/reconcile-dynamic-and-wiki` and published as draft PR #23. Mutagen deployment remains paused until review and merge. +All dp-NN backlog items are implemented. The completed successor is staged on `agent/rebase-pr22-on-pr23`; original draft PR #22 and prerequisite draft PR #23 remain unchanged for history. The exact Paymenter companion is published as draft PR #24. Mutagen deployment remains paused until the successor and companion are reviewed, merged, and separately authorized for deployment. --- @@ -67,20 +67,21 @@ All dp-NN backlog items are implemented. The active reconciliation is staged on > **Claude**: Update this frequently during work, not just at session end. > This survives compaction and helps resume quickly. -**Last checkpoint**: 2026-08-17 -**Working on**: Draft PR #23 reconciliation and Wiki verification -**Status**: Panel changes are preserved on the reconciliation branch; Qoder Wiki pages are migrated to GitHub Wiki and refreshed for the final batched location API flow. +**Last checkpoint**: 2026-08-18 +**Working on**: Exact-SHA review and successor draft PR handoff +**Status**: The full PR #22 rebase is complete with every PR #23 safety fix preserved. `NodeCapacityPolicy`, zero-as-unlimited rejection, API-key encryption/migration, strict inventory validation, sanitized errors, and the private SQLite test database guard are present. The cross-repository PHP 8.3/8.4 SQLite and MariaDB 11/12 matrix is configured and green at the last reviewed commit. **Current file**: PROGRESS.md -**Next action**: Complete exact-SHA review, then fully rebase PR #22 onto this reconciliation before any production merge or deployment. The rebase must retain its explicit `NodeCapacityPolicy`, rejection of Pterodactyl's zero-as-unlimited resource limits, and API-key encryption migration while preserving every PR #23 safety and Wiki change. Resume Mutagen only as a separately authorized deployment step. -**Blockers**: PR #23 must not deploy alone. Stock Pterodactyl does not expose node CPU capacity, uses zero resource limits to mean unlimited, and this branch does not yet encrypt/migrate the stored API key. PR #22 supplies all three protections but overlaps this reconciliation, so it must be fully rebased rather than partially cherry-picked or merged unchanged. No CI checks are configured on PR #23. +**Next action**: Finish the fresh exact-SHA review, publish the successor as a draft PR targeting `dynamic-slider`, and retain PR #22/#23 as superseded history until the replacement path is approved. Resume Mutagen only as a separately authorized deployment step after both repositories are merged and the migration checklist is complete. +**Blockers**: Production deployment remains intentionally paused. The extension successor must ship with Paymenter companion PR #24, database backups and both migration sets, configured per-node capacity policies, confirmed exclusive provisioning control, and an approved deployment window. ### This Session's Changes: -1. Preserved the dp-20 panel close-out without restoring obsolete deployment guidance. -2. Reconciled the location availability path to one `locations/{id}?include=nodes,servers` request and fail-closed capacity parsing, including complete pagination accounting, integral resource values, and duplicate node, server, and location identity rejection. -3. Replaced caller-selected SQLite test paths with the internally generated `:temporary:` database workflow. -4. Migrated the retained Qoder page set to GitHub Wiki and synchronized API, deployment, and testing contracts. -5. Published draft PR #23 for exact-SHA review; Mutagen deployment remains paused. +1. Preserved the useful panel close-out and PR #23 changes, then rebased the complete PR #22 history onto them without rewriting either published draft branch. +2. Consolidated live panel access behind `PterodactylInventoryService`, with complete pagination accounting, integral resource validation, duplicate/orphan rejection, local `NodeCapacityPolicy`, and zero-as-unlimited fail-closed behavior. +3. Restored the Paymenter-owned service and upgrade lifecycle seams, API-key encryption migration, durable commitments, scheduler health checks, and cancellation/provisioning safeguards. +4. Replaced caller-selected SQLite test paths with the process-private `:temporary:` named-memory database workflow, including separate-process coverage. +5. Pinned the audited Paymenter companion, added the cross-repository PHP/SQLite/MariaDB matrix, pinned third-party workflow actions to immutable commits, and completed a read-only live Pterodactyl inventory smoke test. +6. Preserved all 42 migrated Qoder pages, marked superseded deep dives as historical, published the reconciled canonical architecture, and verified the standalone Wiki hierarchy, source links, and anchors. --- From a6fd5fedfaade6f1d02a6a4329e7b5e51aba1fa8 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 03:12:33 +1000 Subject: [PATCH 60/95] docs: refresh reconciled source pins --- .../en/content/API Reference/API Reference.md | 24 +++++++------- .../Architecture Overview.md | 32 +++++++++---------- .../en/content/Core Services/Core Services.md | 2 +- .qoder/repowiki/en/content/Deployment.md | 2 +- .qoder/repowiki/en/content/Event System.md | 2 +- .qoder/repowiki/en/content/Testing.md | 18 +++++------ .../repowiki/en/meta/repowiki-metadata.json | 2 +- 7 files changed, 41 insertions(+), 41 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index c2ca664..91ef7df 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -23,12 +23,12 @@ There are no standalone customer availability, pricing, reservation-create, reservation-confirm, or reservation-extend endpoints. Customer quote failures are generic; upstream bodies and internal exception messages are never returned. -[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php) +[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php) **Referenced Files in This Document** -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php) - [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) - [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) - [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) @@ -82,10 +82,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -124,7 +124,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L17-L22) - [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) - [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) @@ -141,7 +141,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L17-L40) - [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) - [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) @@ -151,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L17-L40) ### Endpoints @@ -190,7 +190,7 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L17-L40) - [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing @@ -229,7 +229,7 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L17-L22) - [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) @@ -313,7 +313,7 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L24-L30) - [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) - [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) @@ -343,7 +343,7 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L32-L40) - [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) @@ -378,7 +378,7 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L32-L40) - [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index 2a4a0f8..f500571 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,16 +2,16 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/DynamicPterodactyl.php) -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/routes/api.php) -- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Services/PterodactylInventoryService.php) -- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Services/ResourceCalculationService.php) -- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Services/ResourceQuoteService.php) -- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Services/ReservationService.php) -- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Services/UpgradeReservationService.php) -- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Models/NodeCapacityPolicy.php) -- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Listeners/CartItemCreatedListener.php) -- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/Listeners/CartItemDeletedListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Services/UpgradeReservationService.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Listeners/CartItemDeletedListener.php) ## Reconciled Architecture @@ -132,9 +132,9 @@ in Paymenter core. For implementation-level detail, use these versioned repository guides: -- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/02-SERVICES.md) -- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/03-API.md) -- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/04-EVENTS.md) -- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/09-IMPLEMENTATION.md) -- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/DECISIONS.md) -- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/PROGRESS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index eed9d8a..7f617dc 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -17,7 +17,7 @@ `SchedulerHealthService`, and the audit/configuration services provide the supporting policies and operator visibility. -[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/02-SERVICES.md) +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/02-SERVICES.md) diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index 5e39d9a..c52d253 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -23,7 +23,7 @@ by the cross-repository workflow. Before enabling dynamic stock: The API key migration encrypts the stored credential. Customer errors remain generic; detailed upstream failures belong only in protected logs. -[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/09-IMPLEMENTATION.md) +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/09-IMPLEMENTATION.md) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index af44888..84f70a3 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -15,7 +15,7 @@ companion lifecycle. The reconciled extension does not register cleanup, reconciliation, capacity alerts, and scheduler-lag checks are registered from `DynamicPterodactyl::boot()`. -[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/04-EVENTS.md) +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/04-EVENTS.md) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 897ff8d..286f14a 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -14,14 +14,14 @@ process-private named-memory database and rejects inherited generated URIs in child processes. MySQL/MariaDB tests may use only the explicitly named `paymenter_test` database while `APP_ENV=testing`. -[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php) and -[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/TestDatabaseGuard.php) +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/TestDatabaseGuard.php) **Referenced Files in This Document** - [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) -- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php) - [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) - [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) - [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) @@ -86,7 +86,7 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) - [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) @@ -97,7 +97,7 @@ U --> AC **Section sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) @@ -142,7 +142,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -361,7 +361,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) @@ -383,7 +383,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -425,7 +425,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/0d0b6169aaef5f44f311f82bae05bbf4060e63c3/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 29d0653..d4b00e4 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"0d0b6169aaef5f44f311f82bae05bbf4060e63c3","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBW0kY68nN6yH347gACSKnGW/GaWsrfe1qmD5Vs4yiF9Bg4+cNg243x5/lrCPGe0ZLa727Kgt90Uf0qPTmGz2CCcagpDlxGuQ7KqPUQcnjLaS5faJVmqkBWfw6JX8uB8qtdCgeBozoNT8CS3Bl+VaFcrfo46PhuL+4MV4UlG69rB+KEYv2FlCDFDg9dsS+3XTkwBCvSqfvBNpmup+JH+w/q41CDiYfTbbURVO8q98JASJEHxb7rNSya1EFRu03Dndw5/hcunp6sW3i/mUBf3rxpXMRj7LhAAzagrVZYsK5LpuTLXislaMmRF+QNJZ+IT2lA/DQouhtUWc62leDrTc90zHDuF0e3jmfC8eu07DCVNzcVaikeY2HvQANYSq9rcpC9dzQDVFpKkVZPyhummuPO6U99ZLXQfwklIsKdCVTSZVinDVknwHBRxCYkuHbrR8PCWVfl3nrZOl4z3lC/mgPD7igYiJ64AUnOrpRNW3FBxgRf+8BvCrHeO/WIMVcJAbwWpx1XZdbGR+ktnHoWF73udn49QqG7nwtZCHkmejnF7RE14lQ8+LnaecPtPbDVehaKMSZUoX61sD47oraIoF5YU4E4zx2W6+7KWhB+NpL6ko1IG+UcHaD4hkEfJeD/2SeBD7vRpayej1ACgV5vne+TGzI7kZjsnKCjMqmxL4YD2RzBYMKD6LQL6+ubIXcmtFJAr/Qf1KdnxmlKveyXnZvX/ndj/g4n7iBoa+G06u5nlxnDftLOS1UX5Akt9Sa4ReIpPgc+Iu4fZiEvIogShhlx03pJAKPKeqY42rc4Hmh/zj2ffRkETYofbIvn6wCSpMGtQgaNCIsoTBzZqBh0tM7Ms2F9sOuNc6VOVytLWrAGs3Uj9mAw1cTz5V3dDkS8Iqc+2KwYHX1PPfXqBnFJ9XWfpzrzj1AUpLdt2Z96y1BKsDO8FeK7GHaIwMaAh0x3oc2MEQ48zBkemSFRqIbRb6rRjJaXwqbblx57l65FhBcMxFJxsPldnLySuNmXFfz1BkfSZ5DNpDxfbRaWAgJ5iptfMKdXbJy30ubNAJBkJhH4W4vLOQclfbDxGrO05ifqQbqraigV+gsHDqbEOiWWDQntcPu4du6DA+lClzPznkDuMn7ja/xjWhR8ohc2fY4GLWlOImAZLQEAyJmjJuZjDb+wqcLkwv/j9SeZbOJGELa6Y6Cr8itehW5lwWc5TsSfqavSxmD9CM2kCWNa9KxKdXaIxsUdn3AszUAdFlaPjG1P92QEIZMq5VR63US8SMFRS/lg2Bu/R10wr78W2ugpCg5hl4fZ5p/1vmKfSOK9ausuHQkeqqTABqn+iCT1Z7fU7QiEJ1KksgoDFkz8d4juqNhT7IjgBmnKpjlFLoMF070nLjTwO0MpA2l6ecAQhNFxkCTTgbwRAIdm91gS5JWtJnfYT+O23P17YXLCRKgLW9r5xM89j/ujErpG3/BIYXQkGGTGjTpO/lzd6VuHMlCDRwq73TZwT6AUgKKmb39ODafcEgXDC0Bwj49ZcUbc5EUw20RKYOccxNuKtBfilv6f7hbd8Hu0elrwUXFysMGHrQEIp5zXnFc3NBoJTtz5sGtxvwxy8KxeukwOhTloRknS/PinVWgDSl7tIsvU41/UPsEcjYzvczZ7nHfW+gpamwJoBNcYBOgGuCXoh+r/X+5NP4J0E8n/b2wCID44OPvacVG4V0qgjxQD4xvuliHGhoyte4iUvy5yOLrxbtwVmw5WBJUPAVwPgvGGRdqqVGnUW9k5T6rUGgAYhhHc5FTr9y4OibhX47uWd5eEv8IHnOhQT5/OyBAM1DOPcI1CQf0W6Pe/UObhm1662/8HXjlFAWsAJiyHi+I4iqPHBoOO9+l5Ng9s7uFUXtS6a2de/JIymAUP30+H8rrNsAGFKDIDiIVgJoPtOqSM+8eDo5CQvS/Wtf9VNIbJ0jbt8M9D79XxKedIjsFMGtgC4JPtycHOsQu3VsEvlFdhN60jr0Dd8w2Fa1hkc=","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"c33704fe9c768c86e67a941d03927b7c29983585","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file From 7040d45d8ddfcdffa71d5c4f3435228c16a9d9d1 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 03:45:07 +1000 Subject: [PATCH 61/95] ci: pin patched companion assets --- .github/workflows/cross-repository-integration.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml index 4c4771f..67278c1 100644 --- a/.github/workflows/cross-repository-integration.yml +++ b/.github/workflows/cross-repository-integration.yml @@ -35,7 +35,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 4bab39fa1ee8ae471a104efda15dd1ac037f209e + ref: f7f10a966c5d119843d9ea7036a3574e3181760b path: paymenter - name: Set up PHP @@ -96,7 +96,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 4bab39fa1ee8ae471a104efda15dd1ac037f209e + ref: f7f10a966c5d119843d9ea7036a3574e3181760b path: paymenter - name: Set up PHP @@ -198,7 +198,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 4bab39fa1ee8ae471a104efda15dd1ac037f209e + ref: f7f10a966c5d119843d9ea7036a3574e3181760b path: paymenter - name: Set up PHP From 17322c63ab4033b10879cc6804a7827c22f92537 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 03:45:07 +1000 Subject: [PATCH 62/95] docs: archive superseded progress details --- PROGRESS.md | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/PROGRESS.md b/PROGRESS.md index 27d73fb..6e3c3fa 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -71,7 +71,7 @@ All dp-NN backlog items are implemented. The completed successor is staged on `a **Working on**: Exact-SHA review and successor draft PR handoff **Status**: The full PR #22 rebase is complete with every PR #23 safety fix preserved. `NodeCapacityPolicy`, zero-as-unlimited rejection, API-key encryption/migration, strict inventory validation, sanitized errors, and the private SQLite test database guard are present. The cross-repository PHP 8.3/8.4 SQLite and MariaDB 11/12 matrix is configured and green at the last reviewed commit. **Current file**: PROGRESS.md -**Next action**: Finish the fresh exact-SHA review, publish the successor as a draft PR targeting `dynamic-slider`, and retain PR #22/#23 as superseded history until the replacement path is approved. Resume Mutagen only as a separately authorized deployment step after both repositories are merged and the migration checklist is complete. +**Next action**: Finish the fresh exact-SHA review, open the successor draft PR targeting `dynamic-slider`, and retain PR #22/#23 as superseded history until the replacement path is approved. Resume Mutagen only as a separately authorized deployment step after both repositories are merged and the migration checklist is complete. **Blockers**: Production deployment remains intentionally paused. The extension successor must ship with Paymenter companion PR #24, database backups and both migration sets, configured per-node capacity policies, confirmed exclusive provisioning control, and an approved deployment window. ### This Session's Changes: @@ -87,6 +87,10 @@ All dp-NN backlog items are implemented. The completed successor is staged on `a ## dp-19 — Wire customer-facing slider to reservation API +> **Historical milestone.** This records the April 2026 implementation. The +> reconciled successor uses customer quote endpoints and Paymenter cart/service +> lifecycle seams instead of the retired public reservation endpoint. + **Status**: Shipped **PR**: committed directly on `dynamic-slider` (default branch; no PR base) **Date**: 2026-04-27 @@ -105,6 +109,10 @@ Closed the architectural gap where `dynamicSliderGroup` Alpine component never c ## dp-18 — Capacity-fanout Performance: batch admin-view Pterodactyl reads +> **Historical milestone.** This records the original batching work. The +> successor centralizes strict paginated location, node, server, and allocation +> reads in `PterodactylInventoryService`. + **Status**: Shipped **PR**: #20 **Merge commit**: be4756f @@ -124,7 +132,12 @@ Update this section: --- -## Up Next +## Historical Implementation Checklist + +> **Archived reference.** The checklist below records the original phased +> implementation and intentionally retains names that were later retired. It is +> not a current source inventory or deployment plan. Use **Current Status** and +> **Current Session State** above for the active contract. ### Phase 1: Foundation (COMPLETE) - [x] Create extension directory structure @@ -184,9 +197,12 @@ See 09-IMPLEMENTATION.md for full phase breakdown. --- -## Blockers / Questions +## Current Deployment Blockers -*None currently* +Production deployment is intentionally paused pending approval and merge of the +extension successor and Paymenter companion PR #24, database backups and both +migration sets, configured per-node capacity policies, confirmed exclusive +provisioning control, and an approved deployment window. I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -124,7 +124,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L17-L22) - [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) - [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) @@ -141,7 +141,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L17-L40) - [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) - [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) @@ -151,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L17-L40) ### Endpoints @@ -190,7 +190,7 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L17-L40) - [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing @@ -229,7 +229,7 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L17-L22) - [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) @@ -313,7 +313,7 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L24-L30) - [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) - [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) @@ -343,7 +343,7 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L32-L40) - [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) @@ -378,7 +378,7 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L32-L40) - [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) diff --git a/.qoder/repowiki/en/content/Admin Interface.md b/.qoder/repowiki/en/content/Admin Interface.md index b8509f2..532aab9 100644 --- a/.qoder/repowiki/en/content/Admin Interface.md +++ b/.qoder/repowiki/en/content/Admin Interface.md @@ -1,24 +1,27 @@ # Admin Interface +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, tables, or API shapes are historical. + + **Referenced Files in This Document** -- [Dashboard.php](file://Admin/Pages/Dashboard.php) -- [NodeMonitoring.php](file://Admin/Pages/NodeMonitoring.php) -- [SetupWizard.php](file://Admin/Pages/SetupWizard.php) -- [AuditLogPage.php](file://Admin/Pages/AuditLogPage.php) -- [ReservationResource.php](file://Admin/Resources/ReservationResource.php) -- [AlertConfigResource.php](file://Admin/Resources/AlertConfigResource.php) -- [dashboard.blade.php](file://resources/views/admin/dashboard.blade.php) -- [node-monitoring.blade.php](file://resources/views/admin/node-monitoring.blade.php) -- [setup-wizard.blade.php](file://resources/views/admin/setup-wizard.blade.php) -- [audit-log.blade.php](file://resources/views/admin/audit-log.blade.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [AuditLogService.php](file://Services/AuditLogService.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [AuditLog.php](file://Models/AuditLog.php) -- [ResourceReservationPolicy.php](file://Policies/ResourceReservationPolicy.php) -- [EnsureUserIsAdmin.php](file://Http/Middleware/EnsureUserIsAdmin.php) +- [Dashboard.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/Dashboard.php) +- [NodeMonitoring.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/NodeMonitoring.php) +- [SetupWizard.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php) +- [AuditLogPage.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php) +- [ReservationResource.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/ReservationResource.php) +- [AlertConfigResource.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php) +- [dashboard.blade.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/dashboard.blade.php) +- [node-monitoring.blade.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/node-monitoring.blade.php) +- [setup-wizard.blade.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/setup-wizard.blade.php) +- [audit-log.blade.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/audit-log.blade.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [AuditLogService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [AuditLog.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php) +- [ResourceReservationPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php) +- [EnsureUserIsAdmin.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php) ## Table of Contents @@ -83,27 +86,27 @@ AL --> ALS ``` **Diagram sources** -- [Dashboard.php:11-25](file://Admin/Pages/Dashboard.php#L11-L25) -- [NodeMonitoring.php:8-20](file://Admin/Pages/NodeMonitoring.php#L8-L20) -- [SetupWizard.php:26-42](file://Admin/Pages/SetupWizard.php#L26-L42) -- [AuditLogPage.php:15-29](file://Admin/Pages/AuditLogPage.php#L15-L29) -- [ReservationResource.php:15-27](file://Admin/Resources/ReservationResource.php#L15-L27) -- [AlertConfigResource.php:27-39](file://Admin/Resources/AlertConfigResource.php#L27-L39) -- [dashboard.blade.php:1-103](file://resources/views/admin/dashboard.blade.php#L1-L103) -- [node-monitoring.blade.php:1-109](file://resources/views/admin/node-monitoring.blade.php#L1-L109) -- [setup-wizard.blade.php:1-5](file://resources/views/admin/setup-wizard.blade.php#L1-L5) -- [audit-log.blade.php:1-47](file://resources/views/admin/audit-log.blade.php#L1-L47) -- [ResourceCalculationService.php:10-22](file://Services/ResourceCalculationService.php#L10-L22) -- [ReservationService.php:16-35](file://Services/ReservationService.php#L16-L35) -- [AuditLogService.php:10-41](file://Services/AuditLogService.php#L10-L41) +- [Dashboard.php:11-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/Dashboard.php#L11-L25) +- [NodeMonitoring.php:8-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/NodeMonitoring.php#L8-L20) +- [SetupWizard.php:26-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L26-L42) +- [AuditLogPage.php:15-29](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L15-L29) +- [ReservationResource.php:15-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/ReservationResource.php#L15-L27) +- [AlertConfigResource.php:27-39](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L27-L39) +- [dashboard.blade.php:1-103](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/dashboard.blade.php#L1-L103) +- [node-monitoring.blade.php:1-109](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/node-monitoring.blade.php#L1-L109) +- [setup-wizard.blade.php:1-5](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/setup-wizard.blade.php#L1-L5) +- [audit-log.blade.php:1-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/audit-log.blade.php#L1-L47) +- [ResourceCalculationService.php:10-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L10-L22) +- [ReservationService.php:16-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L16-L35) +- [AuditLogService.php:10-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L10-L41) **Section sources** -- [Dashboard.php:11-25](file://Admin/Pages/Dashboard.php#L11-L25) -- [NodeMonitoring.php:8-20](file://Admin/Pages/NodeMonitoring.php#L8-L20) -- [SetupWizard.php:26-42](file://Admin/Pages/SetupWizard.php#L26-L42) -- [AuditLogPage.php:15-29](file://Admin/Pages/AuditLogPage.php#L15-L29) -- [ReservationResource.php:15-27](file://Admin/Resources/ReservationResource.php#L15-L27) -- [AlertConfigResource.php:27-39](file://Admin/Resources/AlertConfigResource.php#L27-L39) +- [Dashboard.php:11-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/Dashboard.php#L11-L25) +- [NodeMonitoring.php:8-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/NodeMonitoring.php#L8-L20) +- [SetupWizard.php:26-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L26-L42) +- [AuditLogPage.php:15-29](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L15-L29) +- [ReservationResource.php:15-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/ReservationResource.php#L15-L27) +- [AlertConfigResource.php:27-39](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L27-L39) ## Core Components - Dashboard page: Displays connection status, key stats (products with sliders, pending reservations, revenue, conversion), and per-location capacity with health indicators. @@ -114,16 +117,16 @@ AL --> ALS - Alert config resource: Create/edit/delete alert configurations with thresholds, notification channels, cooldowns, and test send. **Section sources** -- [Dashboard.php:27-73](file://Admin/Pages/Dashboard.php#L27-L73) -- [dashboard.blade.php:1-103](file://resources/views/admin/dashboard.blade.php#L1-L103) -- [NodeMonitoring.php:22-61](file://Admin/Pages/NodeMonitoring.php#L22-L61) -- [node-monitoring.blade.php:1-109](file://resources/views/admin/node-monitoring.blade.php#L1-L109) -- [SetupWizard.php:50-427](file://Admin/Pages/SetupWizard.php#L50-L427) -- [setup-wizard.blade.php:1-5](file://resources/views/admin/setup-wizard.blade.php#L1-L5) -- [AuditLogPage.php:31-103](file://Admin/Pages/AuditLogPage.php#L31-L103) -- [audit-log.blade.php:1-47](file://resources/views/admin/audit-log.blade.php#L1-L47) -- [ReservationResource.php:34-127](file://Admin/Resources/ReservationResource.php#L34-L127) -- [AlertConfigResource.php:41-176](file://Admin/Resources/AlertConfigResource.php#L41-L176) +- [Dashboard.php:27-73](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/Dashboard.php#L27-L73) +- [dashboard.blade.php:1-103](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/dashboard.blade.php#L1-L103) +- [NodeMonitoring.php:22-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/NodeMonitoring.php#L22-L61) +- [node-monitoring.blade.php:1-109](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/node-monitoring.blade.php#L1-L109) +- [SetupWizard.php:50-427](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L50-L427) +- [setup-wizard.blade.php:1-5](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/setup-wizard.blade.php#L1-L5) +- [AuditLogPage.php:31-103](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L103) +- [audit-log.blade.php:1-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/audit-log.blade.php#L1-L47) +- [ReservationResource.php:34-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/ReservationResource.php#L34-L127) +- [AlertConfigResource.php:41-176](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L41-L176) ## Architecture Overview The admin UI renders data via Filament pages/resources which call services. Services interact with Pterodactyl API and internal databases. Policies enforce permissions on sensitive actions. @@ -146,10 +149,10 @@ Page-->>Admin : Rendered Filament view ``` **Diagram sources** -- [Dashboard.php:27-73](file://Admin/Pages/Dashboard.php#L27-L73) -- [NodeMonitoring.php:22-61](file://Admin/Pages/NodeMonitoring.php#L22-L61) -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [ReservationService.php:335-382](file://Services/ReservationService.php#L335-L382) +- [Dashboard.php:27-73](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/Dashboard.php#L27-L73) +- [NodeMonitoring.php:22-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/NodeMonitoring.php#L22-L61) +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [ReservationService.php:335-382](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L335-L382) ## Detailed Component Analysis @@ -175,13 +178,13 @@ ShowErr --> Render ``` **Diagram sources** -- [Dashboard.php:27-73](file://Admin/Pages/Dashboard.php#L27-L73) -- [dashboard.blade.php:1-103](file://resources/views/admin/dashboard.blade.php#L1-L103) -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) +- [Dashboard.php:27-73](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/Dashboard.php#L27-L73) +- [dashboard.blade.php:1-103](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/dashboard.blade.php#L1-L103) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) **Section sources** -- [Dashboard.php:27-115](file://Admin/Pages/Dashboard.php#L27-L115) -- [dashboard.blade.php:1-103](file://resources/views/admin/dashboard.blade.php#L1-L103) +- [Dashboard.php:27-115](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/Dashboard.php#L27-L115) +- [dashboard.blade.php:1-103](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/dashboard.blade.php#L1-L103) ### Node Monitoring - Purpose: Real-time view of node utilization and availability per location. @@ -206,13 +209,13 @@ NM-->>Admin : Render table with utilization ``` **Diagram sources** -- [NodeMonitoring.php:22-61](file://Admin/Pages/NodeMonitoring.php#L22-L61) -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [node-monitoring.blade.php:1-109](file://resources/views/admin/node-monitoring.blade.php#L1-L109) +- [NodeMonitoring.php:22-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/NodeMonitoring.php#L22-L61) +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [node-monitoring.blade.php:1-109](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/node-monitoring.blade.php#L1-L109) **Section sources** -- [NodeMonitoring.php:22-61](file://Admin/Pages/NodeMonitoring.php#L22-L61) -- [node-monitoring.blade.php:1-109](file://resources/views/admin/node-monitoring.blade.php#L1-L109) +- [NodeMonitoring.php:22-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/NodeMonitoring.php#L22-L61) +- [node-monitoring.blade.php:1-109](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/node-monitoring.blade.php#L1-L109) ### Setup Wizard - Purpose: Configure dynamic slider options for a selected product, including pricing models and allowed locations. @@ -238,12 +241,12 @@ G --> |Yes| I["Success Notification & Reset Form"] ``` **Diagram sources** -- [SetupWizard.php:50-427](file://Admin/Pages/SetupWizard.php#L50-L427) -- [setup-wizard.blade.php:1-5](file://resources/views/admin/setup-wizard.blade.php#L1-L5) +- [SetupWizard.php:50-427](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L50-L427) +- [setup-wizard.blade.php:1-5](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/setup-wizard.blade.php#L1-L5) **Section sources** -- [SetupWizard.php:50-509](file://Admin/Pages/SetupWizard.php#L50-L509) -- [setup-wizard.blade.php:1-5](file://resources/views/admin/setup-wizard.blade.php#L1-L5) +- [SetupWizard.php:50-509](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L50-L509) +- [setup-wizard.blade.php:1-5](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/setup-wizard.blade.php#L1-L5) ### Audit Log Viewer - Purpose: Track administrative actions and display recent alert delivery failures. @@ -269,12 +272,12 @@ AuditLogPage --> AuditLog : "queries" ``` **Diagram sources** -- [AuditLogPage.php:31-103](file://Admin/Pages/AuditLogPage.php#L31-L103) -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) +- [AuditLogPage.php:31-103](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L103) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) **Section sources** -- [AuditLogPage.php:31-103](file://Admin/Pages/AuditLogPage.php#L31-L103) -- [audit-log.blade.php:1-47](file://resources/views/admin/audit-log.blade.php#L1-L47) +- [AuditLogPage.php:31-103](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L103) +- [audit-log.blade.php:1-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/audit-log.blade.php#L1-L47) ### Reservation Management Resource - Purpose: Manual intervention for pending reservations (extend TTL, cancel) and bulk cleanup of expired ones. @@ -306,14 +309,14 @@ RR-->>Admin : Confirmation ``` **Diagram sources** -- [ReservationResource.php:87-127](file://Admin/Resources/ReservationResource.php#L87-L127) -- [ReservationService.php:250-281](file://Services/ReservationService.php#L250-L281) -- [ReservationService.php:387-405](file://Services/ReservationService.php#L387-L405) +- [ReservationResource.php:87-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/ReservationResource.php#L87-L127) +- [ReservationService.php:250-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L250-L281) +- [ReservationService.php:387-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L387-L405) **Section sources** -- [ReservationResource.php:34-127](file://Admin/Resources/ReservationResource.php#L34-L127) -- [ReservationService.php:250-405](file://Services/ReservationService.php#L250-L405) -- [ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) +- [ReservationResource.php:34-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/ReservationResource.php#L34-L127) +- [ReservationService.php:250-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L250-L405) +- [ResourceReservationPolicy.php:14-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L68) ### Alert Configuration CRUD - Purpose: Define alert rules per location or globally, set thresholds, choose notification channels, and test alerts. @@ -336,10 +339,10 @@ AlertConfigResource --> AlertService : "uses" ``` **Diagram sources** -- [AlertConfigResource.php:41-176](file://Admin/Resources/AlertConfigResource.php#L41-L176) +- [AlertConfigResource.php:41-176](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L41-L176) **Section sources** -- [AlertConfigResource.php:41-176](file://Admin/Resources/AlertConfigResource.php#L41-L176) +- [AlertConfigResource.php:41-176](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L41-L176) ## Dependency Analysis Key dependencies between admin components and services: @@ -355,20 +358,20 @@ AlertCfg["Alert Config Resource"] --> RCS ``` **Diagram sources** -- [Dashboard.php:27-73](file://Admin/Pages/Dashboard.php#L27-L73) -- [NodeMonitoring.php:22-61](file://Admin/Pages/NodeMonitoring.php#L22-L61) -- [SetupWizard.php:442-457](file://Admin/Pages/SetupWizard.php#L442-L457) -- [AuditLogPage.php:83-103](file://Admin/Pages/AuditLogPage.php#L83-L103) -- [ReservationResource.php:99-123](file://Admin/Resources/ReservationResource.php#L99-L123) -- [AlertConfigResource.php:158-163](file://Admin/Resources/AlertConfigResource.php#L158-L163) +- [Dashboard.php:27-73](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/Dashboard.php#L27-L73) +- [NodeMonitoring.php:22-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/NodeMonitoring.php#L22-L61) +- [SetupWizard.php:442-457](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L442-L457) +- [AuditLogPage.php:83-103](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L83-L103) +- [ReservationResource.php:99-123](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/ReservationResource.php#L99-L123) +- [AlertConfigResource.php:158-163](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L158-L163) **Section sources** -- [Dashboard.php:27-73](file://Admin/Pages/Dashboard.php#L27-L73) -- [NodeMonitoring.php:22-61](file://Admin/Pages/NodeMonitoring.php#L22-L61) -- [SetupWizard.php:442-457](file://Admin/Pages/SetupWizard.php#L442-L457) -- [AuditLogPage.php:83-103](file://Admin/Pages/AuditLogPage.php#L83-L103) -- [ReservationResource.php:99-123](file://Admin/Resources/ReservationResource.php#L99-L123) -- [AlertConfigResource.php:158-163](file://Admin/Resources/AlertConfigResource.php#L158-L163) +- [Dashboard.php:27-73](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/Dashboard.php#L27-L73) +- [NodeMonitoring.php:22-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/NodeMonitoring.php#L22-L61) +- [SetupWizard.php:442-457](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/SetupWizard.php#L442-L457) +- [AuditLogPage.php:83-103](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L83-L103) +- [ReservationResource.php:99-123](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/ReservationResource.php#L99-L123) +- [AlertConfigResource.php:158-163](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L158-L163) ## Performance Considerations - Real-time data: The dashboard and node monitoring fetch live data from Pterodactyl; avoid excessive polling. Use Filament’s poll feature judiciously (e.g., reservations list polls every 30 seconds). @@ -392,10 +395,10 @@ AlertCfg["Alert Config Resource"] --> RCS - For non-admin actors, ensure ownership checks pass. **Section sources** -- [Dashboard.php:27-73](file://Admin/Pages/Dashboard.php#L27-L73) -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) -- [AuditLogPage.php:83-103](file://Admin/Pages/AuditLogPage.php#L83-L103) -- [ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) +- [Dashboard.php:27-73](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/Dashboard.php#L27-L73) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) +- [AuditLogPage.php:83-103](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L83-L103) +- [ResourceReservationPolicy.php:14-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L68) ## Conclusion The Filament 4 admin interface provides a comprehensive operational view of system health, node utilization, and business metrics. Administrators can configure dynamic pricing through the setup wizard, manage reservations manually, and monitor alert delivery effectiveness. Integration with Pterodactyl is real-time and resilient, while policies and middleware enforce secure access. @@ -424,8 +427,8 @@ The Filament 4 admin interface provides a comprehensive operational view of syst - Non-admin users must own the reservation to cancel or extend. **Section sources** -- [ResourceReservationPolicy.php:14-68](file://Policies/ResourceReservationPolicy.php#L14-L68) -- [EnsureUserIsAdmin.php:11-20](file://Http/Middleware/EnsureUserIsAdmin.php#L11-L20) +- [ResourceReservationPolicy.php:14-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L14-L68) +- [EnsureUserIsAdmin.php:11-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L11-L20) ### Customization and Styling - Views: Blade templates under resources/views/admin/ use Filament panel components and Tailwind utility classes for consistent styling. @@ -433,10 +436,10 @@ The Filament 4 admin interface provides a comprehensive operational view of syst - Extensibility: Add custom columns, filters, or actions in resources; customize views with standard Blade patterns. **Section sources** -- [dashboard.blade.php:1-103](file://resources/views/admin/dashboard.blade.php#L1-L103) -- [node-monitoring.blade.php:1-109](file://resources/views/admin/node-monitoring.blade.php#L1-L109) -- [setup-wizard.blade.php:1-5](file://resources/views/admin/setup-wizard.blade.php#L1-L5) -- [audit-log.blade.php:1-47](file://resources/views/admin/audit-log.blade.php#L1-L47) +- [dashboard.blade.php:1-103](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/dashboard.blade.php#L1-L103) +- [node-monitoring.blade.php:1-109](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/node-monitoring.blade.php#L1-L109) +- [setup-wizard.blade.php:1-5](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/setup-wizard.blade.php#L1-L5) +- [audit-log.blade.php:1-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/audit-log.blade.php#L1-L47) ### Integration Points - Pterodactyl API: @@ -449,9 +452,9 @@ The Filament 4 admin interface provides a comprehensive operational view of syst - ResourceReservation and AuditLog define storage structures and relationships. **Section sources** -- [ResourceCalculationService.php:69-141](file://Services/ResourceCalculationService.php#L69-L141) -- [ResourceCalculationService.php:158-195](file://Services/ResourceCalculationService.php#L158-L195) -- [ReservationService.php:335-405](file://Services/ReservationService.php#L335-L405) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) \ No newline at end of file +- [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) +- [ResourceCalculationService.php:158-195](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L158-L195) +- [ReservationService.php:335-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L335-L405) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index f500571..1adb691 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,16 +2,16 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/DynamicPterodactyl.php) -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/routes/api.php) -- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Services/PterodactylInventoryService.php) -- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Services/ResourceCalculationService.php) -- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Services/ResourceQuoteService.php) -- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Services/ReservationService.php) -- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Services/UpgradeReservationService.php) -- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Models/NodeCapacityPolicy.php) -- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Listeners/CartItemCreatedListener.php) -- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/Listeners/CartItemDeletedListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Services/UpgradeReservationService.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Listeners/CartItemDeletedListener.php) ## Reconciled Architecture @@ -132,9 +132,9 @@ in Paymenter core. For implementation-level detail, use these versioned repository guides: -- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/02-SERVICES.md) -- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/03-API.md) -- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/04-EVENTS.md) -- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/09-IMPLEMENTATION.md) -- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/DECISIONS.md) -- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/PROGRESS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Alert Service.md b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Alert Service.md index 151fcc5..3ce8d62 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Alert Service.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Service Layer Design/Alert Service.md @@ -1,20 +1,23 @@ # Alert Service +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, tables, or API shapes are historical. + + **Referenced Files in This Document** -- [AlertService.php](file://Services/AlertService.php) -- [AlertConfig.php](file://Models/AlertConfig.php) -- [AlertDeliveryLog.php](file://Models/AlertDeliveryLog.php) -- [CapacityAlertNotification.php](file://Notifications/CapacityAlertNotification.php) -- [ReservationShortfallNotification.php](file://Notifications/ReservationShortfallNotification.php) -- [AlertDeliveryFailed.php](file://Events/AlertDeliveryFailed.php) -- [DynamicPterodactyl.php](file://DynamicPterodactyl.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [2025_01_01_000004_create_ptero_alert_configs_table.php](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php) -- [AlertConfigObserver.php](file://Models/Observers/AlertConfigObserver.php) -- [AlertConfigResource.php](file://Admin/Resources/AlertConfigResource.php) -- [AlertScheduleTest.php](file://tests/Feature/AlertScheduleTest.php) +- [AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) +- [AlertConfig.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php) +- [AlertDeliveryLog.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php) +- [CapacityAlertNotification.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php) +- [ReservationShortfallNotification.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/ReservationShortfallNotification.php) +- [AlertDeliveryFailed.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [2025_01_01_000004_create_ptero_alert_configs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php) +- [AlertConfigObserver.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php) +- [AlertConfigResource.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php) +- [AlertScheduleTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AlertScheduleTest.php) ## Table of Contents @@ -53,16 +56,16 @@ AlertSvc --> Event["AlertDeliveryFailed event"] ``` **Diagram sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [CapacityAlertNotification.php:19-47](file://Notifications/CapacityAlertNotification.php#L19-L47) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [AlertDeliveryFailed.php:9-16](file://Events/AlertDeliveryFailed.php#L9-L16) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [CapacityAlertNotification.php:19-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php#L19-L47) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [AlertDeliveryFailed.php:9-16](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L16) **Section sources** -- [DynamicPterodactyl.php:96-127](file://DynamicPterodactyl.php#L96-L127) -- [AlertScheduleTest.php:23-33](file://tests/Feature/AlertScheduleTest.php#L23-L33) +- [DynamicPterodactyl.php:96-127](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L96-L127) +- [AlertScheduleTest.php:23-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AlertScheduleTest.php#L23-L33) ## Core Components - AlertService: Orchestrates threshold checks, cooldown enforcement, notification delivery, logging, auditing, and failure events. @@ -75,14 +78,14 @@ AlertSvc --> Event["AlertDeliveryFailed event"] - Admin AlertConfigResource: Filament resource exposing CRUD and a “Test” action to send a sample alert. **Section sources** -- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [CapacityAlertNotification.php:10-47](file://Notifications/CapacityAlertNotification.php#L10-L47) -- [ReservationShortfallNotification.php:10-40](file://Notifications/ReservationShortfallNotification.php#L10-L40) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [AlertConfigObserver.php:8-69](file://Models/Observers/AlertConfigObserver.php#L8-L69) -- [AlertConfigResource.php:150-196](file://Admin/Resources/AlertConfigResource.php#L150-L196) +- [AlertService.php:19-392](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L19-L392) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [CapacityAlertNotification.php:10-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php#L10-L47) +- [ReservationShortfallNotification.php:10-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/ReservationShortfallNotification.php#L10-L40) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [AlertConfigObserver.php:8-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L8-L69) +- [AlertConfigResource.php:150-196](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L150-L196) ## Architecture Overview The service is invoked by a scheduled task registered during extension boot. For each active alert configuration, it determines the scope (global or specific location), fetches current availability from Pterodactyl via ResourceCalculationService, evaluates memory and disk utilization against configured warning/critical thresholds, and dispatches notifications if any thresholds are breached. Cooldown prevents repeated alerts within a configured window. Delivery attempts are recorded, and failures emit an event for downstream handling. @@ -118,14 +121,14 @@ end ``` **Diagram sources** -- [DynamicPterodactyl.php:118-126](file://DynamicPterodactyl.php#L118-L126) -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [CapacityAlertNotification.php:19-47](file://Notifications/CapacityAlertNotification.php#L19-L47) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [AlertDeliveryFailed.php:9-16](file://Events/AlertDeliveryFailed.php#L9-L16) +- [DynamicPterodactyl.php:118-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L118-L126) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [CapacityAlertNotification.php:19-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php#L19-L47) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [AlertDeliveryFailed.php:9-16](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L16) ## Detailed Component Analysis @@ -166,16 +169,16 @@ NextCfg --> End(["Done"]) ``` **Diagram sources** -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) **Section sources** -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) -- [AlertService.php:304-323](file://Services/AlertService.php#L304-L323) -- [AlertService.php:328-369](file://Services/AlertService.php#L328-L369) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) +- [AlertService.php:304-323](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L304-L323) +- [AlertService.php:328-369](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L369) ### AlertConfig Model and Migration - Stores thresholds for memory and disk (warning and critical), notification toggles, recipients, webhook URL, cooldown, activation status, and last notification timestamp. @@ -186,8 +189,8 @@ Migration highlights: - Columns for thresholds, notification settings, cooldown, timestamps, and indexes for efficient querying. **Section sources** -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:9-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L9-L42) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:9-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L9-L42) ### AlertDeliveryLog Model and Migration - Persists each delivery attempt with trigger type, attempted time, channels tried/succeeded/failed, and last error. @@ -198,16 +201,16 @@ Migration highlights: - JSON columns for channel arrays. **Section sources** -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:9-24](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L9-L24) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:9-24](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L9-L24) ### Notifications - CapacityAlertNotification: Sends mail to admins with subject, greeting, lines describing each breach, and a link to edit the alert config. Severity derived from breaches. - ReservationShortfallNotification: Queued mail notifying admins about post-payment reservation shortfalls, including service/invoice IDs, reason, and snapshot details. **Section sources** -- [CapacityAlertNotification.php:10-47](file://Notifications/CapacityAlertNotification.php#L10-L47) -- [ReservationShortfallNotification.php:10-40](file://Notifications/ReservationShortfallNotification.php#L10-L40) +- [CapacityAlertNotification.php:10-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php#L10-L47) +- [ReservationShortfallNotification.php:10-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/ReservationShortfallNotification.php#L10-L40) ### Integration Points - Scheduling: The extension registers a five-minute schedule to run AlertService::checkCapacityAlerts(), without overlapping. @@ -215,9 +218,9 @@ Migration highlights: - Observers: AlertConfigObserver audits creation/update/deletion of alert configs and redacts webhook URLs in audit entries. **Section sources** -- [DynamicPterodactyl.php:118-126](file://DynamicPterodactyl.php#L118-L126) -- [AlertConfigResource.php:150-196](file://Admin/Resources/AlertConfigResource.php#L150-L196) -- [AlertConfigObserver.php:12-69](file://Models/Observers/AlertConfigObserver.php#L12-L69) +- [DynamicPterodactyl.php:118-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L118-L126) +- [AlertConfigResource.php:150-196](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L150-L196) +- [AlertConfigObserver.php:12-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L69) ## Dependency Analysis AlertService depends on: @@ -261,17 +264,17 @@ AlertService --> AlertDeliveryFailed : "dispatches on failure" ``` **Diagram sources** -- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [CapacityAlertNotification.php:10-47](file://Notifications/CapacityAlertNotification.php#L10-L47) -- [ReservationShortfallNotification.php:10-40](file://Notifications/ReservationShortfallNotification.php#L10-L40) -- [AlertDeliveryFailed.php:9-16](file://Events/AlertDeliveryFailed.php#L9-L16) +- [AlertService.php:19-392](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L19-L392) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [CapacityAlertNotification.php:10-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php#L10-L47) +- [ReservationShortfallNotification.php:10-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/ReservationShortfallNotification.php#L10-L40) +- [AlertDeliveryFailed.php:9-16](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L16) **Section sources** -- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [AlertService.php:19-392](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L19-L392) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) ## Performance Considerations - Real-time availability: Availability is fetched directly from Pterodactyl API per check; avoid adding caching unless explicitly required. @@ -296,11 +299,11 @@ Operational checks: - Review audit logs for capacity_alert_sent actions to confirm successful deliveries. **Section sources** -- [AlertService.php:143-179](file://Services/AlertService.php#L143-L179) -- [AlertService.php:182-216](file://Services/AlertService.php#L182-L216) -- [AlertService.php:250-276](file://Services/AlertService.php#L250-L276) -- [AlertConfigResource.php:150-164](file://Admin/Resources/AlertConfigResource.php#L150-L164) -- [AlertScheduleTest.php:23-33](file://tests/Feature/AlertScheduleTest.php#L23-L33) +- [AlertService.php:143-179](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L143-L179) +- [AlertService.php:182-216](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L182-L216) +- [AlertService.php:250-276](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L250-L276) +- [AlertConfigResource.php:150-164](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L150-L164) +- [AlertScheduleTest.php:23-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AlertScheduleTest.php#L23-L33) ## Conclusion The Alert Service provides robust, configurable capacity monitoring with clear separation between evaluation and delivery. It integrates seamlessly with Paymenter’s notification stack, persists delivery history, and supports both proactive scheduling and reactive shortfall notifications. Properly tuned thresholds and cooldowns ensure timely, actionable alerts without overwhelming stakeholders. @@ -361,5 +364,5 @@ ALERT_CONFIG ||--o{ ALERT_DELIVERY_LOG : "has many" ``` **Diagram sources** -- [2025_01_01_000004_create_ptero_alert_configs_table.php:9-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L9-L42) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:9-24](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L9-L24) \ No newline at end of file +- [2025_01_01_000004_create_ptero_alert_configs_table.php:9-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L9-L42) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:9-24](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L9-L24) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Core Services/AlertService.md b/.qoder/repowiki/en/content/Core Services/AlertService.md index 5bd8506..8e47544 100644 --- a/.qoder/repowiki/en/content/Core Services/AlertService.md +++ b/.qoder/repowiki/en/content/Core Services/AlertService.md @@ -1,20 +1,23 @@ # AlertService +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, tables, or API shapes are historical. + + **Referenced Files in This Document** -- [AlertService.php](file://Services/AlertService.php) -- [AlertConfig.php](file://Models/AlertConfig.php) -- [AlertDeliveryLog.php](file://Models/AlertDeliveryLog.php) -- [CapacityAlertNotification.php](file://Notifications/CapacityAlertNotification.php) -- [ReservationShortfallNotification.php](file://Notifications/ReservationShortfallNotification.php) -- [AlertDeliveryFailed.php](file://Events/AlertDeliveryFailed.php) -- [ResourceCalculationService.php](file://Services/ResourceCalculationService.php) -- [AuditLogService.php](file://Services/AuditLogService.php) -- [AuditsExtensionActions.php](file://Services/Concerns/AuditsExtensionActions.php) -- [AlertConfigObserver.php](file://Models/Observers/AlertConfigObserver.php) -- [AlertConfigResource.php](file://Admin/Resources/AlertConfigResource.php) -- [2025_01_01_000004_create_ptero_alert_configs_table.php](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php) +- [AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) +- [AlertConfig.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php) +- [AlertDeliveryLog.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php) +- [CapacityAlertNotification.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php) +- [ReservationShortfallNotification.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/ReservationShortfallNotification.php) +- [AlertDeliveryFailed.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php) +- [ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php) +- [AuditLogService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php) +- [AuditsExtensionActions.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php) +- [AlertConfigObserver.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php) +- [AlertConfigResource.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php) +- [2025_01_01_000004_create_ptero_alert_configs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php) ## Table of Contents @@ -68,19 +71,19 @@ A --> G ``` **Diagram sources** -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [CapacityAlertNotification.php:19-47](file://Notifications/CapacityAlertNotification.php#L19-L47) -- [AlertConfig.php:12-34](file://Models/AlertConfig.php#L12-L34) -- [AlertDeliveryLog.php:12-27](file://Models/AlertDeliveryLog.php#L12-L27) -- [AuditLogService.php:15-40](file://Services/AuditLogService.php#L15-L40) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [CapacityAlertNotification.php:19-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php#L19-L47) +- [AlertConfig.php:12-34](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L12-L34) +- [AlertDeliveryLog.php:12-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L12-L27) +- [AuditLogService.php:15-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L40) **Section sources** -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [AlertConfig.php:12-34](file://Models/AlertConfig.php#L12-L34) -- [AlertDeliveryLog.php:12-27](file://Models/AlertDeliveryLog.php#L12-L27) -- [AuditLogService.php:15-40](file://Services/AuditLogService.php#L15-L40) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [AlertConfig.php:12-34](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L12-L34) +- [AlertDeliveryLog.php:12-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L12-L27) +- [AuditLogService.php:15-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L40) ## Core Components - AlertService: Orchestrates capacity checks, threshold evaluation, notifications, cooldown enforcement, delivery logging, and audit events. @@ -94,16 +97,16 @@ A --> G - AlertConfigResource: Filament admin resource to create/edit/list alert configs and run test notifications. **Section sources** -- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [CapacityAlertNotification.php:10-47](file://Notifications/CapacityAlertNotification.php#L10-L47) -- [ReservationShortfallNotification.php:10-40](file://Notifications/ReservationShortfallNotification.php#L10-L40) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [AuditLogService.php:15-40](file://Services/AuditLogService.php#L15-L40) -- [AuditsExtensionActions.php:10-32](file://Services/Concerns/AuditsExtensionActions.php#L10-L32) -- [AlertConfigObserver.php:12-68](file://Models/Observers/AlertConfigObserver.php#L12-L68) -- [AlertConfigResource.php:41-167](file://Admin/Resources/AlertConfigResource.php#L41-L167) +- [AlertService.php:19-392](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L19-L392) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [CapacityAlertNotification.php:10-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php#L10-L47) +- [ReservationShortfallNotification.php:10-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/ReservationShortfallNotification.php#L10-L40) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [AuditLogService.php:15-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L40) +- [AuditsExtensionActions.php:10-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L32) +- [AlertConfigObserver.php:12-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L68) +- [AlertConfigResource.php:41-167](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L41-L167) ## Architecture Overview The alerting pipeline runs on a schedule: @@ -143,11 +146,11 @@ end ``` **Diagram sources** -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) -- [AlertService.php:128-247](file://Services/AlertService.php#L128-L247) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [AuditLogService.php:15-40](file://Services/AuditLogService.php#L15-L40) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) +- [AlertService.php:128-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L247) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [AuditLogService.php:15-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L40) ## Detailed Component Analysis @@ -188,11 +191,11 @@ Integration points: - Event system for delivery failures. **Section sources** -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) -- [AlertService.php:128-247](file://Services/AlertService.php#L128-L247) -- [AlertService.php:250-299](file://Services/AlertService.php#L250-L299) -- [AlertService.php:304-392](file://Services/AlertService.php#L304-L392) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) +- [AlertService.php:128-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L247) +- [AlertService.php:250-299](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L250-L299) +- [AlertService.php:304-392](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L304-L392) #### Class Diagram ```mermaid @@ -252,12 +255,12 @@ AlertService --> AuditLogService : "audits" ``` **Diagram sources** -- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [CapacityAlertNotification.php:10-47](file://Notifications/CapacityAlertNotification.php#L10-L47) -- [AuditLogService.php:15-40](file://Services/AuditLogService.php#L15-L40) +- [AlertService.php:19-392](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L19-L392) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [CapacityAlertNotification.php:10-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php#L10-L47) +- [AuditLogService.php:15-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L40) ### Alert Configuration Management - Storage: AlertConfig model maps to ptero_alert_configs table with fields for thresholds, channels, cooldown, and active state. @@ -272,10 +275,10 @@ Configuration options: - Scope: location_id selects a specific location; null means all locations. **Section sources** -- [AlertConfig.php:12-56](file://Models/AlertConfig.php#L12-L56) -- [AlertConfigResource.php:41-167](file://Admin/Resources/AlertConfigResource.php#L41-L167) -- [AlertConfigObserver.php:12-68](file://Models/Observers/AlertConfigObserver.php#L12-L68) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [AlertConfig.php:12-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L12-L56) +- [AlertConfigResource.php:41-167](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L41-L167) +- [AlertConfigObserver.php:12-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L68) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) ### Threshold Monitoring and Cooldown - Utilization calculation: memory and disk utilization computed from total_capacity and total_allocated. @@ -305,12 +308,12 @@ UpdateCooldown --> End ``` **Diagram sources** -- [AlertService.php:44-75](file://Services/AlertService.php#L44-L75) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) +- [AlertService.php:44-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L44-L75) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) **Section sources** -- [AlertService.php:44-75](file://Services/AlertService.php#L44-L75) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) +- [AlertService.php:44-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L44-L75) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) ### Notification Channels Integration - Email: Sends CapacityAlertNotification to all users with role_id set. Subject includes severity and scope. Body lists breached resources with usage percentage and thresholds. Includes action link to edit alert config. @@ -324,10 +327,10 @@ Custom channels: - To add a custom channel, extend sendNotifications logic to include additional channel attempts, track success/failure, and persist results in delivery logs. Ensure you handle errors and emit AlertDeliveryFailed when all channels fail. **Section sources** -- [AlertService.php:128-247](file://Services/AlertService.php#L128-L247) -- [CapacityAlertNotification.php:19-47](file://Notifications/CapacityAlertNotification.php#L19-L47) -- [AlertDeliveryLog.php:12-27](file://Models/AlertDeliveryLog.php#L12-L27) -- [AlertDeliveryFailed.php:9-15](file://Events/AlertDeliveryFailed.php#L9-L15) +- [AlertService.php:128-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L247) +- [CapacityAlertNotification.php:19-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php#L19-L47) +- [AlertDeliveryLog.php:12-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L12-L27) +- [AlertDeliveryFailed.php:9-15](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L15) ### Delivery Status Tracking and Failure Handling - Delivery logs capture: @@ -341,9 +344,9 @@ Custom channels: - Audit logs are not written for failed-only deliveries. **Section sources** -- [AlertService.php:218-247](file://Services/AlertService.php#L218-L247) -- [AlertService.php:250-299](file://Services/AlertService.php#L250-L299) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) +- [AlertService.php:218-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L218-L247) +- [AlertService.php:250-299](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L250-L299) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) ### Alert Scheduling Mechanism - The AlertService exposes checkCapacityAlerts(), which iterates active alert configs and processes them. @@ -353,7 +356,7 @@ Custom channels: Note: The exact scheduling invocation is outside the AlertService file; ensure your application’s scheduler calls checkCapacityAlerts() periodically. **Section sources** -- [AlertService.php:33-42](file://Services/AlertService.php#L33-L42) +- [AlertService.php:33-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L42) ### Reservation Shortfall Notifications - notifyShortfall sends emails to all users with role_id set about reservation shortfalls or state drift after payment. @@ -361,8 +364,8 @@ Note: The exact scheduling invocation is outside the AlertService file; ensure y - Errors are logged per recipient without failing the caller. **Section sources** -- [AlertService.php:328-361](file://Services/AlertService.php#L328-L361) -- [ReservationShortfallNotification.php:10-40](file://Notifications/ReservationShortfallNotification.php#L10-L40) +- [AlertService.php:328-361](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L328-L361) +- [ReservationShortfallNotification.php:10-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/ReservationShortfallNotification.php#L10-L40) ### Audit Logging Integration - Successful capacity alerts are audited via AuditsExtensionActions::safeAudit with action 'capacity_alert_sent', entity type 'alert_config', and payload including channels, severity, breached resources, and location scope. @@ -370,10 +373,10 @@ Note: The exact scheduling invocation is outside the AlertService file; ensure y - AuditLogService writes to ptero_audit_logs with user context and request metadata. **Section sources** -- [AlertService.php:238-245](file://Services/AlertService.php#L238-L245) -- [AuditsExtensionActions.php:10-32](file://Services/Concerns/AuditsExtensionActions.php#L10-L32) -- [AlertConfigObserver.php:12-68](file://Models/Observers/AlertConfigObserver.php#L12-L68) -- [AuditLogService.php:15-40](file://Services/AuditLogService.php#L15-L40) +- [AlertService.php:238-245](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L238-L245) +- [AuditsExtensionActions.php:10-32](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L32) +- [AlertConfigObserver.php:12-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L68) +- [AuditLogService.php:15-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L40) ## Dependency Analysis - AlertService depends on: @@ -397,15 +400,15 @@ RCS --> API["Pterodactyl API"] ``` **Diagram sources** -- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) -- [CapacityAlertNotification.php:10-47](file://Notifications/CapacityAlertNotification.php#L10-L47) -- [AlertDeliveryFailed.php:9-15](file://Events/AlertDeliveryFailed.php#L9-L15) -- [AuditLogService.php:15-40](file://Services/AuditLogService.php#L15-L40) +- [AlertService.php:19-392](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L19-L392) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) +- [CapacityAlertNotification.php:10-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php#L10-L47) +- [AlertDeliveryFailed.php:9-15](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L15) +- [AuditLogService.php:15-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L40) **Section sources** -- [AlertService.php:19-392](file://Services/AlertService.php#L19-L392) -- [ResourceCalculationService.php:26-67](file://Services/ResourceCalculationService.php#L26-L67) +- [AlertService.php:19-392](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L19-L392) +- [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) ## Performance Considerations - Real-time availability: ResourceCalculationService queries Pterodactyl API directly; avoid caching to maintain accuracy. @@ -435,10 +438,10 @@ Common issues and resolutions: - Resolution: Confirm at least one channel succeeded; audit is only written on success. **Section sources** -- [AlertService.php:143-179](file://Services/AlertService.php#L143-L179) -- [AlertService.php:182-216](file://Services/AlertService.php#L182-L216) -- [AlertService.php:218-247](file://Services/AlertService.php#L218-L247) -- [AlertService.php:250-299](file://Services/AlertService.php#L250-L299) +- [AlertService.php:143-179](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L143-L179) +- [AlertService.php:182-216](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L182-L216) +- [AlertService.php:218-247](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L218-L247) +- [AlertService.php:250-299](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L250-L299) ## Conclusion AlertService provides robust capacity monitoring with configurable thresholds, cooldown-based rate limiting, multi-channel notifications, detailed delivery tracking, and audit logging. It integrates seamlessly with ResourceCalculationService for real-time availability and supports extensibility for custom channels. Proper scheduling and configuration ensure reliable alerting without spamming administrators. @@ -464,10 +467,10 @@ AlertService provides robust capacity monitoring with configurable thresholds, c - last_error **Section sources** -- [AlertConfig.php:12-34](file://Models/AlertConfig.php#L12-L34) -- [AlertDeliveryLog.php:12-27](file://Models/AlertDeliveryLog.php#L12-L27) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) +- [AlertConfig.php:12-34](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L12-L34) +- [AlertDeliveryLog.php:12-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L12-L27) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) ### Admin Dashboard Integration - Filament AlertConfigResource provides: @@ -479,4 +482,4 @@ AlertService provides robust capacity monitoring with configurable thresholds, c - Test action to send a sample notification **Section sources** -- [AlertConfigResource.php:41-167](file://Admin/Resources/AlertConfigResource.php#L41-L167) \ No newline at end of file +- [AlertConfigResource.php:41-167](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L41-L167) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index 7f617dc..1936770 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -17,7 +17,7 @@ `SchedulerHealthService`, and the audit/configuration services provide the supporting policies and operator visibility. -[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/02-SERVICES.md) +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/02-SERVICES.md) diff --git a/.qoder/repowiki/en/content/Database Schema/Alert Configurations Table.md b/.qoder/repowiki/en/content/Database Schema/Alert Configurations Table.md index 1ac15ed..0fc6564 100644 --- a/.qoder/repowiki/en/content/Database Schema/Alert Configurations Table.md +++ b/.qoder/repowiki/en/content/Database Schema/Alert Configurations Table.md @@ -1,18 +1,21 @@ # Alert Configurations Table +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, tables, or API shapes are historical. + + **Referenced Files in This Document** -- [AlertConfig.php](file://Models/AlertConfig.php) -- [2025_01_01_000004_create_ptero_alert_configs_table.php](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) -- [AlertDeliveryLog.php](file://Models/AlertDeliveryLog.php) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php) -- [AlertService.php](file://Services/AlertService.php) -- [CapacityAlertNotification.php](file://Notifications/CapacityAlertNotification.php) -- [ReservationShortfallNotification.php](file://Notifications/ReservationShortfallNotification.php) -- [AlertConfigObserver.php](file://Models/Observers/AlertConfigObserver.php) -- [AlertConfigResource.php](file://Admin/Resources/AlertConfigResource.php) -- [AlertDeliveryFailed.php](file://Events/AlertDeliveryFailed.php) -- [AlertScheduleTest.php](file://tests/Feature/AlertScheduleTest.php) +- [AlertConfig.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php) +- [2025_01_01_000004_create_ptero_alert_configs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) +- [AlertDeliveryLog.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php) +- [AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) +- [CapacityAlertNotification.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php) +- [ReservationShortfallNotification.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/ReservationShortfallNotification.php) +- [AlertConfigObserver.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php) +- [AlertConfigResource.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php) +- [AlertDeliveryFailed.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php) +- [AlertScheduleTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AlertScheduleTest.php) ## Table of Contents @@ -63,18 +66,18 @@ S --> E ``` **Diagram sources** -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AlertConfigObserver.php:12-68](file://Models/Observers/AlertConfigObserver.php#L12-L68) -- [AlertConfigResource.php:41-167](file://Admin/Resources/AlertConfigResource.php#L41-L167) -- [CapacityAlertNotification.php:14-47](file://Notifications/CapacityAlertNotification.php#L14-L47) -- [ReservationShortfallNotification.php:10-40](file://Notifications/ReservationShortfallNotification.php#L10-L40) -- [AlertDeliveryFailed.php:9-16](file://Events/AlertDeliveryFailed.php#L9-L16) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AlertConfigObserver.php:12-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L68) +- [AlertConfigResource.php:41-167](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L41-L167) +- [CapacityAlertNotification.php:14-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php#L14-L47) +- [ReservationShortfallNotification.php:10-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/ReservationShortfallNotification.php#L10-L40) +- [AlertDeliveryFailed.php:9-16](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L16) **Section sources** -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertConfigResource.php:41-167](file://Admin/Resources/AlertConfigResource.php#L41-L167) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertConfigResource.php:41-167](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L41-L167) ## Core Components - Alert configuration model defines fields for scope, thresholds, notification toggles, recipients, webhook URL, cooldown, last notification timestamp, and active status. @@ -84,11 +87,11 @@ S --> E - Admin resource provides form validation and UI for managing alert configurations. **Section sources** -- [AlertConfig.php:12-34](file://Models/AlertConfig.php#L12-L34) -- [AlertDeliveryLog.php:12-31](file://Models/AlertDeliveryLog.php#L12-L31) -- [AlertService.php:33-248](file://Services/AlertService.php#L33-L248) -- [AlertConfigObserver.php:12-68](file://Models/Observers/AlertConfigObserver.php#L12-L68) -- [AlertConfigResource.php:41-167](file://Admin/Resources/AlertConfigResource.php#L41-L167) +- [AlertConfig.php:12-34](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L12-L34) +- [AlertDeliveryLog.php:12-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L12-L31) +- [AlertService.php:33-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L248) +- [AlertConfigObserver.php:12-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L68) +- [AlertConfigResource.php:41-167](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L41-L167) ## Architecture Overview The alerting system runs on a schedule that invokes the alert service to check all active alert configurations. For each configuration, it determines whether to evaluate global or location-specific metrics, computes utilization percentages, compares them against warning/critical thresholds, and if breached, attempts notification delivery through enabled channels. On success, it updates the last notification timestamp and persists delivery logs. Failures emit an event for further handling. @@ -121,11 +124,11 @@ end ``` **Diagram sources** -- [AlertService.php:33-75](file://Services/AlertService.php#L33-L75) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) +- [AlertService.php:33-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L33-L75) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) ## Detailed Component Analysis @@ -157,8 +160,8 @@ Typical usage patterns: - Channels: enable email and/or webhook; provide webhook_url when using webhooks. **Section sources** -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) -- [AlertConfig.php:12-34](file://Models/AlertConfig.php#L12-L34) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [AlertConfig.php:12-34](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L12-L34) ### Schema: ptero_alert_delivery_log - Purpose: Records each alert delivery attempt with outcome and error context. @@ -171,8 +174,8 @@ Typical usage patterns: - Relationship: belongs to AlertConfig. **Section sources** -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) -- [AlertDeliveryLog.php:12-31](file://Models/AlertDeliveryLog.php#L12-L31) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-24](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L24) +- [AlertDeliveryLog.php:12-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L12-L31) ### Trigger Conditions and Threshold Evaluation - Utilization calculation: @@ -217,11 +220,11 @@ Skip --> End ``` **Diagram sources** -- [AlertService.php:44-75](file://Services/AlertService.php#L44-L75) -- [AlertService.php:77-126](file://Services/AlertService.php#L77-L126) +- [AlertService.php:44-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L44-L75) +- [AlertService.php:77-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L126) **Section sources** -- [AlertService.php:44-126](file://Services/AlertService.php#L44-L126) +- [AlertService.php:44-126](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L44-L126) ### Notification Delivery and Channels - Email: @@ -264,13 +267,13 @@ end ``` **Diagram sources** -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) -- [CapacityAlertNotification.php:14-47](file://Notifications/CapacityAlertNotification.php#L14-L47) -- [AlertDeliveryFailed.php:9-16](file://Events/AlertDeliveryFailed.php#L9-L16) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) +- [CapacityAlertNotification.php:14-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php#L14-L47) +- [AlertDeliveryFailed.php:9-16](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Events/AlertDeliveryFailed.php#L9-L16) **Section sources** -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) -- [CapacityAlertNotification.php:14-47](file://Notifications/CapacityAlertNotification.php#L14-L47) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) +- [CapacityAlertNotification.php:14-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Notifications/CapacityAlertNotification.php#L14-L47) ### Observer Pattern and Automatic Validation - Observer hooks into model lifecycle events (created, updated, deleted). @@ -310,12 +313,12 @@ AlertConfigObserver --> AuditLogService : "logs changes" ``` **Diagram sources** -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AlertConfigObserver.php:12-68](file://Models/Observers/AlertConfigObserver.php#L12-L68) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AlertConfigObserver.php:12-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L68) **Section sources** -- [AlertConfigObserver.php:12-68](file://Models/Observers/AlertConfigObserver.php#L12-L68) -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) +- [AlertConfigObserver.php:12-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L68) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) ### Admin Interface and Configuration Validation - Form fields enforce ranges and types: @@ -333,7 +336,7 @@ AlertConfigObserver --> AuditLogService : "logs changes" - Test notification using current config **Section sources** -- [AlertConfigResource.php:41-167](file://Admin/Resources/AlertConfigResource.php#L41-L167) +- [AlertConfigResource.php:41-167](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L41-L167) ### Integration Points and Examples - Typical alert setups: @@ -374,15 +377,15 @@ ResUI["AlertConfigResource"] --> Svc ``` **Diagram sources** -- [AlertService.php:23-28](file://Services/AlertService.php#L23-L28) -- [AlertService.php:128-248](file://Services/AlertService.php#L128-L248) -- [AlertConfigObserver.php:12-68](file://Models/Observers/AlertConfigObserver.php#L12-L68) -- [AlertConfigResource.php:27-31](file://Admin/Resources/AlertConfigResource.php#L27-L31) +- [AlertService.php:23-28](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L23-L28) +- [AlertService.php:128-248](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L128-L248) +- [AlertConfigObserver.php:12-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L68) +- [AlertConfigResource.php:27-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L27-L31) **Section sources** -- [AlertService.php:23-28](file://Services/AlertService.php#L23-L28) -- [AlertConfigObserver.php:12-68](file://Models/Observers/AlertConfigObserver.php#L12-L68) -- [AlertConfigResource.php:27-31](file://Admin/Resources/AlertConfigResource.php#L27-L31) +- [AlertService.php:23-28](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L23-L28) +- [AlertConfigObserver.php:12-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L68) +- [AlertConfigResource.php:27-31](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Resources/AlertConfigResource.php#L27-L31) ## Performance Considerations - Cooldown mechanism prevents excessive notifications and reduces load on email/webhook channels. @@ -409,10 +412,10 @@ Common issues and diagnostics: - Confirm capacity alert schedule is registered and running without overlap **Section sources** -- [AlertService.php:143-180](file://Services/AlertService.php#L143-L180) -- [AlertService.php:182-216](file://Services/AlertService.php#L182-L216) -- [AlertService.php:250-276](file://Services/AlertService.php#L250-L276) -- [AlertScheduleTest.php:23-33](file://tests/Feature/AlertScheduleTest.php#L23-L33) +- [AlertService.php:143-180](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L143-L180) +- [AlertService.php:182-216](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L182-L216) +- [AlertService.php:250-276](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L250-L276) +- [AlertScheduleTest.php:23-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/AlertScheduleTest.php#L23-L33) ## Conclusion The alert configurations table centralizes capacity monitoring rules, notification preferences, and channel settings with clear scoping and cooldown controls. The alert service evaluates thresholds, delivers notifications via email and webhooks, enforces cooldowns, and maintains detailed delivery logs. The observer pattern ensures secure and auditable changes to alert configurations. Together, these components provide a robust, extensible alerting framework suitable for production environments. @@ -441,8 +444,8 @@ The alert configurations table centralizes capacity monitoring rules, notificati - is_active: boolean **Section sources** -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) -- [AlertConfig.php:12-34](file://Models/AlertConfig.php#L12-L34) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [AlertConfig.php:12-34](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L12-L34) ### Example Configurations - Global alerting: diff --git a/.qoder/repowiki/en/content/Database Schema/Audit Logs Table.md b/.qoder/repowiki/en/content/Database Schema/Audit Logs Table.md index 9a34b19..c3f6acc 100644 --- a/.qoder/repowiki/en/content/Database Schema/Audit Logs Table.md +++ b/.qoder/repowiki/en/content/Database Schema/Audit Logs Table.md @@ -1,17 +1,20 @@ # Audit Logs Table +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, tables, or API shapes are historical. + + **Referenced Files in This Document** -- [AuditLog.php](file://Models/AuditLog.php) -- [2025_01_01_000003_create_ptero_audit_logs_table.php](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) -- [AuditLogService.php](file://Services/AuditLogService.php) -- [AuditsExtensionActions.php](file://Services/Concerns/AuditsExtensionActions.php) -- [AlertConfigObserver.php](file://Models/Observers/AlertConfigObserver.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [AlertService.php](file://Services/AlertService.php) -- [ConfigOptionSetupService.php](file://Services/ConfigOptionSetupService.php) -- [AuditLogPage.php](file://Admin/Pages/AuditLogPage.php) -- [audit-log.blade.php](file://resources/views/admin/audit-log.blade.php) +- [AuditLog.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php) +- [2025_01_01_000003_create_ptero_audit_logs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) +- [AuditLogService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php) +- [AuditsExtensionActions.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php) +- [AlertConfigObserver.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) +- [ConfigOptionSetupService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php) +- [AuditLogPage.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php) +- [audit-log.blade.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/resources/views/admin/audit-log.blade.php) ## Table of Contents @@ -60,21 +63,21 @@ Model --> M ``` **Diagram sources** -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AuditLogService.php:10-82](file://Services/AuditLogService.php#L10-L82) -- [AuditsExtensionActions.php:8-33](file://Services/Concerns/AuditsExtensionActions.php#L8-L33) -- [ReservationService.php:102-112](file://Services/ReservationService.php#L102-L112) -- [AlertService.php:238-245](file://Services/AlertService.php#L238-L245) -- [ConfigOptionSetupService.php:69-74](file://Services/ConfigOptionSetupService.php#L69-L74) -- [AlertConfigObserver.php:12-59](file://Models/Observers/AlertConfigObserver.php#L12-L59) -- [AuditLogPage.php:31-80](file://Admin/Pages/AuditLogPage.php#L31-L80) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) +- [AuditLogService.php:10-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L10-L82) +- [AuditsExtensionActions.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L8-L33) +- [ReservationService.php:102-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L102-L112) +- [AlertService.php:238-245](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L238-L245) +- [ConfigOptionSetupService.php:69-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L69-L74) +- [AlertConfigObserver.php:12-59](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L59) +- [AuditLogPage.php:31-80](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L80) **Section sources** -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AuditLogService.php:10-82](file://Services/AuditLogService.php#L10-L82) -- [AuditLogPage.php:31-80](file://Admin/Pages/AuditLogPage.php#L31-L80) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) +- [AuditLogService.php:10-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L10-L82) +- [AuditLogPage.php:31-80](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L80) ## Core Components - Schema and model: The ptero_audit_logs table stores who performed an action, what was changed, change details, request context, and timestamp. The Eloquent model disables automatic timestamps and casts JSON fields to arrays. @@ -89,10 +92,10 @@ Key responsibilities: - Persist request context (ip_address, user_agent) and created_at. **Section sources** -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AuditLogService.php:15-82](file://Services/AuditLogService.php#L15-L82) -- [AuditLogPage.php:31-80](file://Admin/Pages/AuditLogPage.php#L31-L80) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) +- [AuditLogService.php:15-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L82) +- [AuditLogPage.php:31-80](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L80) ## Architecture Overview The audit logging architecture follows a service-oriented pattern with a shared trait to ensure consistent, resilient logging across components. @@ -113,9 +116,9 @@ DB-->>Admin : Paginated results ``` **Diagram sources** -- [AuditsExtensionActions.php:10-33](file://Services/Concerns/AuditsExtensionActions.php#L10-L33) -- [AuditLogService.php:15-82](file://Services/AuditLogService.php#L15-L82) -- [AuditLogPage.php:31-80](file://Admin/Pages/AuditLogPage.php#L31-L80) +- [AuditsExtensionActions.php:10-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L33) +- [AuditLogService.php:15-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L82) +- [AuditLogPage.php:31-80](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L80) ## Detailed Component Analysis @@ -150,8 +153,8 @@ Complexity notes: - The table is append-only; rows are never updated after creation. **Section sources** -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) ### Logging Patterns - Centralized writes via AuditLogService::log(): @@ -175,15 +178,15 @@ Typical audit entries: - Setup run: action=setup_run, entity_type=product_config, payload includes sliders configured and count. **Section sources** -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) -- [AuditsExtensionActions.php:10-33](file://Services/Concerns/AuditsExtensionActions.php#L10-L33) -- [AlertConfigObserver.php:12-59](file://Models/Observers/AlertConfigObserver.php#L12-L59) -- [ReservationService.php:102-112](file://Services/ReservationService.php#L102-L112) -- [ReservationService.php:191-196](file://Services/ReservationService.php#L191-L196) -- [ReservationService.php:234-238](file://Services/ReservationService.php#L234-L238) -- [ReservationService.php:273-278](file://Services/ReservationService.php#L273-L278) -- [AlertService.php:238-245](file://Services/AlertService.php#L238-L245) -- [ConfigOptionSetupService.php:69-74](file://Services/ConfigOptionSetupService.php#L69-L74) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) +- [AuditsExtensionActions.php:10-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L33) +- [AlertConfigObserver.php:12-59](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L59) +- [ReservationService.php:102-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L102-L112) +- [ReservationService.php:191-196](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L191-L196) +- [ReservationService.php:234-238](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L234-L238) +- [ReservationService.php:273-278](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L273-L278) +- [AlertService.php:238-245](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L238-L245) +- [ConfigOptionSetupService.php:69-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L69-L74) ### Querying and Filtering - Filtered retrieval: @@ -201,8 +204,8 @@ Example filter usage: - Show only updates to alert configurations. **Section sources** -- [AuditLogService.php:46-82](file://Services/AuditLogService.php#L46-L82) -- [AuditLogPage.php:31-80](file://Admin/Pages/AuditLogPage.php#L31-L80) +- [AuditLogService.php:46-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L46-L82) +- [AuditLogPage.php:31-80](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L80) ### Relationship to Other Components - Reservations: @@ -261,12 +264,12 @@ AuditLogService --> AuditLog : "persists" ``` **Diagram sources** -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AuditLogService.php:15-82](file://Services/AuditLogService.php#L15-L82) -- [ReservationService.php:102-112](file://Services/ReservationService.php#L102-L112) -- [AlertConfigObserver.php:12-59](file://Models/Observers/AlertConfigObserver.php#L12-L59) -- [AlertService.php:238-245](file://Services/AlertService.php#L238-L245) -- [ConfigOptionSetupService.php:69-74](file://Services/ConfigOptionSetupService.php#L69-L74) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) +- [AuditLogService.php:15-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L82) +- [ReservationService.php:102-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L102-L112) +- [AlertConfigObserver.php:12-59](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L59) +- [AlertService.php:238-245](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L238-L245) +- [ConfigOptionSetupService.php:69-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L69-L74) ## Dependency Analysis - Direct dependencies: @@ -284,9 +287,9 @@ AuditLogService --> AuditLog : "persists" Potential circular dependencies: None observed. **Section sources** -- [AuditLogService.php:1-41](file://Services/AuditLogService.php#L1-L41) -- [AuditLogPage.php:31-80](file://Admin/Pages/AuditLogPage.php#L31-L80) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:42-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L42-L47) +- [AuditLogService.php:1-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L1-L41) +- [AuditLogPage.php:31-80](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L31-L80) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:42-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L42-L47) ## Performance Considerations - Indexing strategy: @@ -323,9 +326,9 @@ Operational checks: - Review admin UI filters to ensure they match expected entity types and actions. **Section sources** -- [AuditsExtensionActions.php:10-33](file://Services/Concerns/AuditsExtensionActions.php#L10-L33) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:36-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L36-L47) +- [AuditsExtensionActions.php:10-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php#L10-L33) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:36-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L36-L47) ## Conclusion The audit logs table provides a robust, indexed foundation for tracking administrative and system events across reservations, alert configurations, and product setup processes. The service layer centralizes logging, while the admin UI offers practical filtering and visualization. With careful retention policies and targeted queries, the audit trail remains performant and actionable for administrators. @@ -365,12 +368,12 @@ The audit logs table provides a robust, indexed foundation for tracking administ - payload: sliders configured, count **Section sources** -- [ReservationService.php:102-112](file://Services/ReservationService.php#L102-L112) -- [ReservationService.php:191-196](file://Services/ReservationService.php#L191-L196) -- [ReservationService.php:234-238](file://Services/ReservationService.php#L234-L238) -- [ReservationService.php:273-278](file://Services/ReservationService.php#L273-L278) -- [AlertService.php:238-245](file://Services/AlertService.php#L238-L245) -- [ConfigOptionSetupService.php:69-74](file://Services/ConfigOptionSetupService.php#L69-L74) +- [ReservationService.php:102-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L102-L112) +- [ReservationService.php:191-196](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L191-L196) +- [ReservationService.php:234-238](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L234-L238) +- [ReservationService.php:273-278](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L273-L278) +- [AlertService.php:238-245](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L238-L245) +- [ConfigOptionSetupService.php:69-74](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php#L69-L74) ### Admin Filtering Capabilities - Filters supported in the admin table: @@ -380,5 +383,5 @@ The audit logs table provides a robust, indexed foundation for tracking administ - entity_id, user_id, date_from, date_to **Section sources** -- [AuditLogPage.php:64-78](file://Admin/Pages/AuditLogPage.php#L64-L78) -- [AuditLogService.php:46-69](file://Services/AuditLogService.php#L46-L69) \ No newline at end of file +- [AuditLogPage.php:64-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Admin/Pages/AuditLogPage.php#L64-L78) +- [AuditLogService.php:46-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L46-L69) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Database Schema/Database Schema.md b/.qoder/repowiki/en/content/Database Schema/Database Schema.md index 633270c..d738c5e 100644 --- a/.qoder/repowiki/en/content/Database Schema/Database Schema.md +++ b/.qoder/repowiki/en/content/Database Schema/Database Schema.md @@ -1,20 +1,23 @@ # Database Schema +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, tables, or API shapes are historical. + + **Referenced Files in This Document** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) -- [2026_04_22_000001_drop_released_from_reservation_status.php](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) -- [2025_01_01_000003_create_ptero_audit_logs_table.php](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) -- [2025_01_01_000004_create_ptero_alert_configs_table.php](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php) -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [AuditLog.php](file://Models/AuditLog.php) -- [AlertConfig.php](file://Models/AlertConfig.php) -- [AlertDeliveryLog.php](file://Models/AlertDeliveryLog.php) -- [ReservationService.php](file://Services/ReservationService.php) -- [AuditLogService.php](file://Services/AuditLogService.php) -- [AlertService.php](file://Services/AlertService.php) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php) +- [2026_04_22_000001_drop_released_from_reservation_status.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) +- [2025_01_01_000003_create_ptero_audit_logs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) +- [2025_01_01_000004_create_ptero_alert_configs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [AuditLog.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php) +- [AlertConfig.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php) +- [AlertDeliveryLog.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) +- [AuditLogService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php) +- [AlertService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php) ## Table of Contents @@ -73,23 +76,23 @@ MD --> D ``` **Diagram sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-61](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L61) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-40](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L40) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-41](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L41) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-23](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L23) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [AlertService.php:77-101](file://Services/AlertService.php#L77-L101) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L61) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L40) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L41) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-23](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L23) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [AlertService.php:77-101](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L101) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) **Section sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-61](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L61) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-40](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L40) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-41](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L41) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-23](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L23) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L61) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L40) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L41) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-23](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L23) ## Core Components - Resource reservations: track temporary holds with token, TTL, and status transitions; include idempotency support and foreign keys to cart, service, and user @@ -98,10 +101,10 @@ MD --> D - Alert delivery log: records of attempted alert deliveries, channels tried/succeeded/failed, and last error **Section sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) ## Architecture Overview The data layer is driven by migrations and enforced by Eloquent models and services. ReservationService orchestrates reservation creation, confirmation, cancellation, extension, cleanup, and statistics using pessimistic locking and idempotency. AlertService evaluates thresholds against availability and writes delivery logs. AuditLogService persists audit entries with request context. @@ -122,10 +125,10 @@ RS-->>Client : {token, node_id, expires_at, status} ``` **Diagram sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-61](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L61) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-40](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L40) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L61) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L40) ## Detailed Component Analysis @@ -218,19 +221,19 @@ class ResourceReservation { ``` **Diagram sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-61](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L61) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:11-19](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L11-L19) -- [2026_04_22_000001_drop_released_from_reservation_status.php:10-18](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L10-L18) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L61) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:11-19](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L11-L19) +- [2026_04_22_000001_drop_released_from_reservation_status.php:10-18](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L10-L18) **Section sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-61](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L61) -- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:11-19](file://database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L11-L19) -- [2026_04_22_000001_drop_released_from_reservation_status.php:10-18](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L10-L18) -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) -- [ReservationService.php:335-405](file://Services/ReservationService.php#L335-L405) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-61](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L61) +- [2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php:11-19](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php#L11-L19) +- [2026_04_22_000001_drop_released_from_reservation_status.php:10-18](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L10-L18) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L281) +- [ReservationService.php:335-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L335-L405) ### Audit Logs - Purpose: Capture administrative actions and system events with actor context and change details @@ -272,13 +275,13 @@ Insert --> End([Done]) ``` **Diagram sources** -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-40](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L40) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L40) **Section sources** -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-40](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L40) -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AuditLogService.php:15-82](file://Services/AuditLogService.php#L15-L82) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L40) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) +- [AuditLogService.php:15-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L82) ### Alert Configurations - Purpose: Define capacity monitoring thresholds and notification preferences per location or globally @@ -335,13 +338,13 @@ class AlertConfig { ``` **Diagram sources** -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-41](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L41) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L41) **Section sources** -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-41](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L41) -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AlertService.php:77-101](file://Services/AlertService.php#L77-L101) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L41) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AlertService.php:77-101](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L101) ### Alert Delivery Log - Purpose: Record each attempt to deliver alerts, including channels tried, success/failure, and errors @@ -379,13 +382,13 @@ class AlertDeliveryLog { ``` **Diagram sources** -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-23](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L23) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-23](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L23) **Section sources** -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-23](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L23) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [AlertService.php:191-293](file://Services/AlertService.php#L191-L293) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:11-23](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L11-L23) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [AlertService.php:191-293](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L191-L293) ## Dependency Analysis - ReservationService depends on NodeSelectionService to pick nodes and on AuditLogService to record actions @@ -405,18 +408,18 @@ ALS --> ACfg["ptero_alert_configs"] ``` **Diagram sources** -- [ReservationService.php:20-35](file://Services/ReservationService.php#L20-L35) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [AlertService.php:77-101](file://Services/AlertService.php#L77-L101) -- [AlertService.php:191-293](file://Services/AlertService.php#L191-L293) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) +- [ReservationService.php:20-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L20-L35) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [AlertService.php:77-101](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L101) +- [AlertService.php:191-293](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L191-L293) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) **Section sources** -- [ReservationService.php:20-35](file://Services/ReservationService.php#L20-L35) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [AlertService.php:77-101](file://Services/AlertService.php#L77-L101) -- [AlertService.php:191-293](file://Services/AlertService.php#L191-L293) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) +- [ReservationService.php:20-35](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L20-L35) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [AlertService.php:77-101](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L101) +- [AlertService.php:191-293](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L191-L293) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) ## Performance Considerations - Use existing indexes for efficient filtering: @@ -450,10 +453,10 @@ ALS --> ACfg["ptero_alert_configs"] - Validate user context and request metadata availability **Section sources** -- [ReservationService.php:125-141](file://Services/ReservationService.php#L125-L141) -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [AlertService.php:191-293](file://Services/AlertService.php#L191-L293) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) +- [ReservationService.php:125-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L125-L141) +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [AlertService.php:191-293](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L191-L293) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) ## Conclusion The data model provides robust support for temporary resource reservations with strong concurrency controls, comprehensive auditability, and configurable capacity alerting. Proper use of indexes, scopes, and service-layer logic ensures scalability and reliability under load. @@ -473,9 +476,9 @@ USERS ||--o{ PTERO_AUDIT_LOGS : "user_id FK" ``` **Diagram sources** -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:64-77](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L64-L77) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:42-46](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L42-L46) -- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:13-16](file://database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L13-L16) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:64-77](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L64-L77) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:42-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L42-L46) +- [2026_04_26_000001_create_ptero_alert_delivery_log_table.php:13-16](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_26_000001_create_ptero_alert_delivery_log_table.php#L13-L16) ### Common Queries Reference - Create reservation: see ReservationService::create @@ -490,8 +493,8 @@ USERS ||--o{ PTERO_AUDIT_LOGS : "user_id FK" - Evaluate alerts: see AlertService threshold checks **Section sources** -- [ReservationService.php:43-141](file://Services/ReservationService.php#L43-L141) -- [ReservationService.php:166-281](file://Services/ReservationService.php#L166-L281) -- [ReservationService.php:335-405](file://Services/ReservationService.php#L335-L405) -- [AuditLogService.php:15-82](file://Services/AuditLogService.php#L15-L82) -- [AlertService.php:77-101](file://Services/AlertService.php#L77-L101) \ No newline at end of file +- [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) +- [ReservationService.php:166-281](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L166-L281) +- [ReservationService.php:335-405](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L335-L405) +- [AuditLogService.php:15-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L82) +- [AlertService.php:77-101](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AlertService.php#L77-L101) \ No newline at end of file diff --git a/.qoder/repowiki/en/content/Database Schema/Model Relationships and Eloquent Models.md b/.qoder/repowiki/en/content/Database Schema/Model Relationships and Eloquent Models.md index 6e8332b..a1f3c34 100644 --- a/.qoder/repowiki/en/content/Database Schema/Model Relationships and Eloquent Models.md +++ b/.qoder/repowiki/en/content/Database Schema/Model Relationships and Eloquent Models.md @@ -1,18 +1,21 @@ # Model Relationships and Eloquent Models +> **Preserved Qoder snapshot.** This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, [[Architecture Overview|Architecture-Overview]] is canonical; references below to retired controllers, listeners, services, tables, or API shapes are historical. + + **Referenced Files in This Document** -- [ResourceReservation.php](file://Models/ResourceReservation.php) -- [AlertConfig.php](file://Models/AlertConfig.php) -- [AuditLog.php](file://Models/AuditLog.php) -- [AlertDeliveryLog.php](file://Models/AlertDeliveryLog.php) -- [AlertConfigObserver.php](file://Models/Observers/AlertConfigObserver.php) -- [AuditLogService.php](file://Services/AuditLogService.php) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) -- [2025_01_01_000003_create_ptero_audit_logs_table.php](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) -- [2025_01_01_000004_create_ptero_alert_configs_table.php](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) -- [2026_04_22_000001_drop_released_from_reservation_status.php](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) -- [ReservationService.php](file://Services/ReservationService.php) +- [ResourceReservation.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php) +- [AlertConfig.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php) +- [AuditLog.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php) +- [AlertDeliveryLog.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php) +- [AlertConfigObserver.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php) +- [AuditLogService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php) +- [2025_01_01_000003_create_ptero_audit_logs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php) +- [2025_01_01_000004_create_ptero_alert_configs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php) +- [2026_04_22_000001_drop_released_from_reservation_status.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php) +- [ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) ## Table of Contents @@ -73,28 +76,28 @@ M4 -.enum change.-> RR ``` **Diagram sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AlertConfigObserver.php:8-69](file://Models/Observers/AlertConfigObserver.php#L8-L69) -- [AuditLogService.php:10-82](file://Services/AuditLogService.php#L10-L82) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) +- [AlertConfigObserver.php:8-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L8-L69) +- [AuditLogService.php:10-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L10-L82) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) **Section sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [AlertConfigObserver.php:8-69](file://Models/Observers/AlertConfigObserver.php#L8-L69) -- [AuditLogService.php:10-82](file://Services/AuditLogService.php#L10-L82) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [AlertConfigObserver.php:8-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L8-L69) +- [AuditLogService.php:10-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L10-L82) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) ## Core Components - ResourceReservation: Represents a reserved compute slot with user/service linkage, pricing snapshot, and lifecycle status. Provides scopes for pending and expired states. @@ -109,11 +112,11 @@ Key behaviors: - AlertConfigObserver writes audit entries on create/update/delete, redacting sensitive webhook URLs before logging. **Section sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [AlertConfigObserver.php:8-69](file://Models/Observers/AlertConfigObserver.php#L8-L69) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [AlertConfigObserver.php:8-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L8-L69) ## Architecture Overview The models interact through relationships and observers to enforce business rules and maintain auditability. @@ -190,12 +193,12 @@ AuditLogService --> "AuditLog" : writes ``` **Diagram sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AlertConfigObserver.php:8-69](file://Models/Observers/AlertConfigObserver.php#L8-L69) -- [AuditLogService.php:10-82](file://Services/AuditLogService.php#L10-L82) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) +- [AlertConfigObserver.php:8-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L8-L69) +- [AuditLogService.php:10-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L10-L82) ## Detailed Component Analysis @@ -228,10 +231,10 @@ Best practices: - When updating status, ensure idempotency and avoid race conditions using pessimistic locking where appropriate. **Section sources** -- [ResourceReservation.php:10-65](file://Models/ResourceReservation.php#L10-L65) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) -- [ReservationService.php:296-330](file://Services/ReservationService.php#L296-L330) +- [ResourceReservation.php:10-65](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L10-L65) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) +- [ReservationService.php:296-330](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L296-L330) #### ResourceReservation State Flow ```mermaid @@ -272,10 +275,10 @@ Best practices: - Ensure webhook_url is never exposed in logs or responses; rely on observer redaction. **Section sources** -- [AlertConfig.php:8-56](file://Models/AlertConfig.php#L8-L56) -- [AlertDeliveryLog.php:8-33](file://Models/AlertDeliveryLog.php#L8-L33) -- [AlertConfigObserver.php:8-69](file://Models/Observers/AlertConfigObserver.php#L8-L69) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [AlertConfig.php:8-56](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L8-L56) +- [AlertDeliveryLog.php:8-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L8-L33) +- [AlertConfigObserver.php:8-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L8-L69) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) #### AlertConfig Observer Sequence ```mermaid @@ -296,9 +299,9 @@ Obs-->>App : complete ``` **Diagram sources** -- [AlertConfigObserver.php:12-68](file://Models/Observers/AlertConfigObserver.php#L12-L68) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [AlertConfigObserver.php:12-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L68) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) ### AuditLog Model and Usage Patterns - Purpose: Centralized, immutable audit trail for critical actions across the system. @@ -324,9 +327,9 @@ Best practices: - Use getEntityHistory for UIs showing change timelines. **Section sources** -- [AuditLog.php:7-37](file://Models/AuditLog.php#L7-L37) -- [AuditLogService.php:10-82](file://Services/AuditLogService.php#L10-L82) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [AuditLog.php:7-37](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AuditLog.php#L7-L37) +- [AuditLogService.php:10-82](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L10-L82) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) ### Common Model Interactions and Best Practices - Relationship queries: @@ -361,24 +364,24 @@ M4["Status enum migration"] --> RR ``` **Diagram sources** -- [ResourceReservation.php:38-46](file://Models/ResourceReservation.php#L38-L46) -- [AlertConfig.php:52-55](file://Models/AlertConfig.php#L52-L55) -- [AlertConfigObserver.php:5-10](file://Models/Observers/AlertConfigObserver.php#L5-L10) -- [AuditLogService.php:10-41](file://Services/AuditLogService.php#L10-L41) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) +- [ResourceReservation.php:38-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L38-L46) +- [AlertConfig.php:52-55](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L52-L55) +- [AlertConfigObserver.php:5-10](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L5-L10) +- [AuditLogService.php:10-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L10-L41) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) **Section sources** -- [ResourceReservation.php:38-46](file://Models/ResourceReservation.php#L38-L46) -- [AlertConfig.php:52-55](file://Models/AlertConfig.php#L52-L55) -- [AlertConfigObserver.php:5-10](file://Models/Observers/AlertConfigObserver.php#L5-L10) -- [AuditLogService.php:10-41](file://Services/AuditLogService.php#L10-L41) -- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](file://database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) -- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](file://database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) -- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](file://database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) +- [ResourceReservation.php:38-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/ResourceReservation.php#L38-L46) +- [AlertConfig.php:52-55](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L52-L55) +- [AlertConfigObserver.php:5-10](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L5-L10) +- [AuditLogService.php:10-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L10-L41) +- [2025_01_01_000001_create_ptero_resource_reservations_table.php:11-78](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php#L11-L78) +- [2025_01_01_000004_create_ptero_alert_configs_table.php:11-42](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php#L11-L42) +- [2025_01_01_000003_create_ptero_audit_logs_table.php:11-47](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php#L11-L47) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) ## Performance Considerations - Indexes: @@ -404,11 +407,11 @@ M4["Status enum migration"] --> RR - Check TTL handling via expires_at and scopes; verify cleanup processes update expired statuses. **Section sources** -- [AlertConfig.php:28-34](file://Models/AlertConfig.php#L28-L34) -- [AlertDeliveryLog.php:12-27](file://Models/AlertDeliveryLog.php#L12-L27) -- [AlertConfigObserver.php:12-68](file://Models/Observers/AlertConfigObserver.php#L12-L68) -- [AuditLogService.php:15-41](file://Services/AuditLogService.php#L15-L41) -- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](file://database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) +- [AlertConfig.php:28-34](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertConfig.php#L28-L34) +- [AlertDeliveryLog.php:12-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/AlertDeliveryLog.php#L12-L27) +- [AlertConfigObserver.php:12-68](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Models/Observers/AlertConfigObserver.php#L12-L68) +- [AuditLogService.php:15-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/AuditLogService.php#L15-L41) +- [2026_04_22_000001_drop_released_from_reservation_status.php:8-27](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2026_04_22_000001_drop_released_from_reservation_status.php#L8-L27) ## Conclusion The models form a cohesive system for managing resource reservations, alerting, and auditing: diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index c52d253..7663069 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -23,7 +23,7 @@ by the cross-repository workflow. Before enabling dynamic stock: The API key migration encrypts the stored credential. Customer errors remain generic; detailed upstream failures belong only in protected logs. -[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/09-IMPLEMENTATION.md) +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/09-IMPLEMENTATION.md) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index 84f70a3..ec0f07f 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -15,7 +15,7 @@ companion lifecycle. The reconciled extension does not register cleanup, reconciliation, capacity alerts, and scheduler-lag checks are registered from `DynamicPterodactyl::boot()`. -[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/04-EVENTS.md) +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/04-EVENTS.md) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 286f14a..bd5bc3b 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -14,14 +14,14 @@ process-private named-memory database and rejects inherited generated URIs in child processes. MySQL/MariaDB tests may use only the explicitly named `paymenter_test` database while `APP_ENV=testing`. -[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php) and -[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/TestDatabaseGuard.php) +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/TestDatabaseGuard.php) **Referenced Files in This Document** - [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) -- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php) - [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) - [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) - [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) @@ -86,7 +86,7 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) - [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) @@ -97,7 +97,7 @@ U --> AC **Section sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) @@ -142,7 +142,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -361,7 +361,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) @@ -383,7 +383,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -425,7 +425,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/c33704fe9c768c86e67a941d03927b7c29983585/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index d4b00e4..066c600 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"c33704fe9c768c86e67a941d03927b7c29983585","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"17322c63ab4033b10879cc6804a7827c22f92537","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file From 0c6d3011dc01c8cd9632e89fdbc662327417fb13 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 04:35:45 +1000 Subject: [PATCH 64/95] fix: restrict alert webhooks to public endpoints --- Admin/Resources/AlertConfigResource.php | 2 + Rules/PublicWebhookUrl.php | 29 ++++ Services/AlertService.php | 16 +- Services/WebhookEndpointPolicy.php | 201 +++++++++++++++++++++++ tests/Unit/AlertServiceTest.php | 51 +++++- tests/Unit/WebhookEndpointPolicyTest.php | 88 ++++++++++ 6 files changed, 381 insertions(+), 6 deletions(-) create mode 100644 Rules/PublicWebhookUrl.php create mode 100644 Services/WebhookEndpointPolicy.php create mode 100644 tests/Unit/WebhookEndpointPolicyTest.php diff --git a/Admin/Resources/AlertConfigResource.php b/Admin/Resources/AlertConfigResource.php index 6335b7a..534d4b8 100644 --- a/Admin/Resources/AlertConfigResource.php +++ b/Admin/Resources/AlertConfigResource.php @@ -21,6 +21,7 @@ use Paymenter\Extensions\Others\DynamicPterodactyl\Admin\Resources\AlertConfigResource\Pages\EditAlertConfig; use Paymenter\Extensions\Others\DynamicPterodactyl\Admin\Resources\AlertConfigResource\Pages\ListAlertConfigs; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\AlertConfig; +use Paymenter\Extensions\Others\DynamicPterodactyl\Rules\PublicWebhookUrl; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AlertService; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceCalculationService; @@ -118,6 +119,7 @@ public static function form(Schema $schema): Schema TextInput::make('webhook_url') ->label('Webhook URL') ->url() + ->rules([new PublicWebhookUrl]) ->visible(fn (Get $get) => $get('webhook_notifications')) ->placeholder('https://...'), diff --git a/Rules/PublicWebhookUrl.php b/Rules/PublicWebhookUrl.php new file mode 100644 index 0000000..ca22431 --- /dev/null +++ b/Rules/PublicWebhookUrl.php @@ -0,0 +1,29 @@ +policy ?? new WebhookEndpointPolicy)->requestOptions($value); + } catch (\InvalidArgumentException $exception) { + $fail($exception->getMessage()); + } + } +} diff --git a/Services/AlertService.php b/Services/AlertService.php index 7b7dda0..2e0ada2 100644 --- a/Services/AlertService.php +++ b/Services/AlertService.php @@ -25,9 +25,15 @@ class AlertService private ResourceCalculationService $resourceService; - public function __construct(ResourceCalculationService $resourceService) - { + private WebhookEndpointPolicy $webhookEndpointPolicy; + + public function __construct( + ResourceCalculationService $resourceService, + ?WebhookEndpointPolicy $webhookEndpointPolicy = null, + ) { $this->resourceService = $resourceService; + $this->webhookEndpointPolicy = $webhookEndpointPolicy + ?? new WebhookEndpointPolicy; } /** @@ -272,10 +278,14 @@ private function sendNotifications(object $config, array $availability, array $a $channelsTried[] = 'webhook'; try { + $requestOptions = $this->webhookEndpointPolicy->requestOptions( + (string) $config->webhook_url + ); + // Format for Discord webhook compatibility $alertColor = collect($alerts)->contains('type', 'critical') ? 16711680 : 16776960; // Red or Yellow - Http::timeout(10)->post($config->webhook_url, [ + Http::withOptions($requestOptions)->timeout(10)->post($config->webhook_url, [ 'content' => "**Capacity Alert** - {$locationName}", 'embeds' => [[ 'title' => 'Resource Usage Alert', diff --git a/Services/WebhookEndpointPolicy.php b/Services/WebhookEndpointPolicy.php new file mode 100644 index 0000000..245da98 --- /dev/null +++ b/Services/WebhookEndpointPolicy.php @@ -0,0 +1,201 @@ +resolveAddresses = $resolveAddresses + ?? static fn (string $host): array => self::lookupAddresses($host); + } + + public function requestOptions(string $url): array + { + $parts = $this->parse($url); + $host = $parts['host']; + $port = $parts['port']; + $addresses = ($this->resolveAddresses)($host); + + if (! is_array($addresses) || $addresses === []) { + throw new \InvalidArgumentException( + 'The webhook host must resolve to a public IP address.' + ); + } + + $addresses = array_values(array_unique($addresses)); + foreach ($addresses as $address) { + if (! is_string($address) || ! $this->isPublicAddress($address)) { + throw new \InvalidArgumentException( + 'The webhook host must resolve only to public IP addresses.' + ); + } + } + + $address = $addresses[0]; + if (filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false) { + $address = '['.$address.']'; + } + + return [ + 'allow_redirects' => false, + 'curl' => [ + CURLOPT_PROTOCOLS => CURLPROTO_HTTPS, + CURLOPT_PROXY => '', + CURLOPT_RESOLVE => ["{$host}:{$port}:{$address}"], + ], + ]; + } + + private function parse(string $url): array + { + $url = trim($url); + if ($url === '' || preg_match('/[\x00-\x20\x7f]/', $url) === 1) { + throw new \InvalidArgumentException( + 'The webhook URL must be an absolute HTTPS URL without whitespace.' + ); + } + + try { + $parts = parse_url($url); + } catch (\ValueError $exception) { + throw new \InvalidArgumentException( + 'The webhook URL is invalid.', + previous: $exception + ); + } + + if (! is_array($parts)) { + throw new \InvalidArgumentException('The webhook URL is invalid.'); + } + + $scheme = strtolower((string) ($parts['scheme'] ?? '')); + $host = strtolower(rtrim((string) ($parts['host'] ?? ''), '.')); + if ($scheme !== 'https' || $host === '') { + throw new \InvalidArgumentException( + 'The webhook URL must use HTTPS and include a host.' + ); + } + + if ( + array_key_exists('user', $parts) + || array_key_exists('pass', $parts) + || array_key_exists('fragment', $parts) + ) { + throw new \InvalidArgumentException( + 'The webhook URL cannot contain user information or a fragment.' + ); + } + + $port = isset($parts['port']) ? (int) $parts['port'] : 443; + if ($port < 1 || $port > 65535) { + throw new \InvalidArgumentException( + 'The webhook URL contains an invalid port.' + ); + } + + if ( + filter_var($host, FILTER_VALIDATE_IP) === false + && ! $this->isValidHostname($host) + ) { + throw new \InvalidArgumentException( + 'The webhook URL contains an invalid host.' + ); + } + + return [ + 'host' => $host, + 'port' => $port, + ]; + } + + private function isValidHostname(string $host): bool + { + if (strlen($host) > 253) { + return false; + } + + foreach (explode('.', $host) as $label) { + if ( + $label === '' + || strlen($label) > 63 + || preg_match('/^(?!-)[a-z0-9-]+(? ['93.184.216.34'] + ) + ); } private function invokeSendNotifications(AlertService $service, object $config, array $availability, array $alerts): mixed @@ -503,6 +509,40 @@ public function test_alert_with_failed_webhook_records_channels_failed(): void Log::shouldHaveReceived('error')->with('Webhook notification failed', Mockery::any()); } + public function test_non_public_webhook_is_rejected_before_an_http_request(): void + { + $dispatcher = $this->bindEventDispatcherMock(); + Http::preventStrayRequests(); + Log::spy(); + + $service = $this->makeService(new WebhookEndpointPolicy( + static fn (string $host): array => ['127.0.0.1'] + )); + $result = $this->invokeSendNotifications( + $service, + (object) [ + 'id' => 43, + 'location_id' => 1, + 'location_name' => 'Test', + 'email_notifications' => false, + 'notification_emails' => json_encode([]), + 'webhook_notifications' => true, + 'webhook_url' => 'https://hooks.example.com/test', + ], + ['total_capacity' => ['memory' => 100, 'disk' => 100], 'total_allocated' => ['memory' => 90, 'disk' => 90]], + [['type' => 'warning', 'resource' => 'memory', 'utilization' => 90.0, 'usage_percent' => 90.0, 'threshold' => 80]], + ); + + $this->assertFalse($result); + Http::assertNothingSent(); + $dispatcher->shouldHaveReceived('dispatch')->with(Mockery::type(AlertDeliveryFailed::class)); + Log::shouldHaveReceived('error')->with( + 'Webhook notification failed', + Mockery::on(fn (array $context) => $context['alert_config_id'] === 43 + && $context['webhook_host'] === 'hooks.example.com') + ); + } + public function test_alert_with_no_recipients_does_not_deliver_email(): void { $dispatcher = $this->bindEventDispatcherMock(); @@ -541,7 +581,12 @@ class AlertServiceAuditTest extends LaravelTestCase private function makeService(ResourceCalculationService $resourceService): AlertService { - return new AlertService($resourceService); + return new AlertService( + $resourceService, + new WebhookEndpointPolicy( + static fn (string $host): array => ['93.184.216.34'] + ) + ); } private function runCheck(AlertService $service, AlertConfig $alertConfig): void diff --git a/tests/Unit/WebhookEndpointPolicyTest.php b/tests/Unit/WebhookEndpointPolicyTest.php new file mode 100644 index 0000000..42f7ae5 --- /dev/null +++ b/tests/Unit/WebhookEndpointPolicyTest.php @@ -0,0 +1,88 @@ +assertSame('hooks.example.com', $host); + + return ['93.184.216.34']; + }); + + $options = $policy->requestOptions( + 'https://hooks.example.com:8443/path?token=secret' + ); + + $this->assertFalse($options['allow_redirects']); + $this->assertSame(CURLPROTO_HTTPS, $options['curl'][CURLOPT_PROTOCOLS]); + $this->assertSame('', $options['curl'][CURLOPT_PROXY]); + $this->assertSame( + ['hooks.example.com:8443:93.184.216.34'], + $options['curl'][CURLOPT_RESOLVE] + ); + } + + #[DataProvider('blockedEndpointProvider')] + public function test_unsafe_webhook_endpoints_are_rejected( + string $url, + array $addresses, + ): void { + $policy = new WebhookEndpointPolicy( + static fn (string $host): array => $addresses + ); + + $this->expectException(\InvalidArgumentException::class); + + $policy->requestOptions($url); + } + + public static function blockedEndpointProvider(): array + { + return [ + 'plain HTTP' => ['http://hooks.example.com/path', ['93.184.216.34']], + 'credentials' => ['https://user:pass@hooks.example.com/path', ['93.184.216.34']], + 'fragment' => ['https://hooks.example.com/path#internal', ['93.184.216.34']], + 'loopback IPv4' => ['https://127.0.0.1/path', ['127.0.0.1']], + 'private IPv4' => ['https://10.0.0.1/path', ['10.0.0.1']], + 'carrier-grade NAT IPv4' => ['https://100.64.0.1/path', ['100.64.0.1']], + 'link-local IPv4' => ['https://169.254.169.254/path', ['169.254.169.254']], + 'benchmark IPv4' => ['https://198.18.0.1/path', ['198.18.0.1']], + 'loopback IPv6' => ['https://[::1]/path', ['::1']], + 'reserved IPv4' => ['https://hooks.example.com/path', ['203.0.113.10']], + 'multicast IPv4' => ['https://hooks.example.com/path', ['224.0.0.1']], + 'documentation IPv6' => ['https://hooks.example.com/path', ['2001:db8::1']], + 'multicast IPv6' => ['https://hooks.example.com/path', ['ff00::1']], + 'mixed DNS response' => ['https://hooks.example.com/path', ['93.184.216.34', '10.0.0.1']], + 'missing DNS response' => ['https://hooks.example.com/path', []], + ]; + } + + public function test_validation_rule_reuses_the_public_endpoint_policy(): void + { + $rule = new PublicWebhookUrl(new WebhookEndpointPolicy( + static fn (string $host): array => ['127.0.0.1'] + )); + $messages = []; + + $rule->validate( + 'webhook_url', + 'https://localhost/hook', + static function (string $message) use (&$messages): void { + $messages[] = $message; + } + ); + + $this->assertSame( + ['The webhook host must resolve only to public IP addresses.'], + $messages + ); + } +} From 37c4a45853ec2c9a1741caba3b6ca7f7bb7519a8 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 04:36:05 +1000 Subject: [PATCH 65/95] docs: record staging lifecycle release gate --- PROGRESS.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/PROGRESS.md b/PROGRESS.md index 6e3c3fa..0047682 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -72,7 +72,7 @@ All dp-NN backlog items are implemented. The completed successor is staged on `a **Status**: The full PR #22 rebase is complete with every PR #23 safety fix preserved. `NodeCapacityPolicy`, zero-as-unlimited rejection, API-key encryption/migration, strict inventory validation, sanitized errors, and the private SQLite test database guard are present. The cross-repository PHP 8.3/8.4 SQLite and MariaDB 11/12 matrix is configured and green at the last reviewed commit. **Current file**: PROGRESS.md **Next action**: Finish the fresh exact-SHA review, open the successor draft PR targeting `dynamic-slider`, and retain PR #22/#23 as superseded history until the replacement path is approved. Resume Mutagen only as a separately authorized deployment step after both repositories are merged and the migration checklist is complete. -**Blockers**: Production deployment remains intentionally paused. The extension successor must ship with Paymenter companion PR #24, database backups and both migration sets, configured per-node capacity policies, confirmed exclusive provisioning control, and an approved deployment window. +**Blockers**: Production deployment remains intentionally paused. The extension successor must ship with Paymenter companion PR #24, database backups and both migration sets, configured per-node capacity policies, confirmed exclusive provisioning control, a successful real-panel staging lifecycle canary, and an approved deployment window. ### This Session's Changes: @@ -202,7 +202,8 @@ See 09-IMPLEMENTATION.md for full phase breakdown. Production deployment is intentionally paused pending approval and merge of the extension successor and Paymenter companion PR #24, database backups and both migration sets, configured per-node capacity policies, confirmed exclusive -provisioning control, and an approved deployment window. +provisioning control, a successful real-panel staging lifecycle canary, and an +approved deployment window. I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -124,7 +124,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L17-L22) - [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) - [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) @@ -141,7 +141,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L17-L40) - [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) - [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) @@ -151,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L17-L40) ### Endpoints @@ -190,7 +190,7 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L17-L40) - [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing @@ -229,7 +229,7 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L17-L22) - [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) @@ -313,7 +313,7 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L24-L30) - [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) - [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) @@ -343,7 +343,7 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L32-L40) - [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) @@ -378,7 +378,7 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L32-L40) - [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index 1adb691..53c0577 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,16 +2,17 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/DynamicPterodactyl.php) -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/routes/api.php) -- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Services/PterodactylInventoryService.php) -- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Services/ResourceCalculationService.php) -- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Services/ResourceQuoteService.php) -- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Services/ReservationService.php) -- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Services/UpgradeReservationService.php) -- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Models/NodeCapacityPolicy.php) -- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Listeners/CartItemCreatedListener.php) -- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/Listeners/CartItemDeletedListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Services/UpgradeReservationService.php) +- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Services/WebhookEndpointPolicy.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Listeners/CartItemDeletedListener.php) ## Reconciled Architecture @@ -124,6 +125,9 @@ in Paymenter core. cleanup and reconciliation failures visible. - Customer responses never expose upstream bodies, API keys, node identities, or internal exception details. +- Alert webhooks must use public HTTPS endpoints. Delivery revalidates every + resolved address, rejects non-public or mixed DNS answers, disables redirects + and proxies, and pins the connection to a validated address. - The test harness accepts only an explicitly named test database or the private `:temporary:` named-memory SQLite claim; production or shared databases are rejected before Paymenter boots. @@ -132,9 +136,9 @@ in Paymenter core. For implementation-level detail, use these versioned repository guides: -- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/02-SERVICES.md) -- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/03-API.md) -- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/04-EVENTS.md) -- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/09-IMPLEMENTATION.md) -- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/DECISIONS.md) -- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/PROGRESS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index 1936770..e484661 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -17,7 +17,7 @@ `SchedulerHealthService`, and the audit/configuration services provide the supporting policies and operator visibility. -[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/02-SERVICES.md) +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/02-SERVICES.md) diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index 7663069..8323c5c 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -16,14 +16,18 @@ by the cross-repository workflow. Before enabling dynamic stock: server moves, resizes, creates, or allocation assignments invalidate the reservation guarantee. 5. Run the setup wizard, the cross-repository PHPUnit workflow, scheduler - heartbeat checks, and a read-only live inventory smoke test. -6. Resume deployment synchronization only after the exact commits are reviewed + heartbeat checks, a read-only live inventory smoke test, and a real-panel + staging lifecycle canary covering checkout, payment, provisioning, upgrade, + renewal, cancellation, and recovery. +6. Configure alert webhooks only to public HTTPS endpoints; delivery rejects + non-public or mixed DNS answers and does not follow redirects or proxies. +7. Resume deployment synchronization only after the exact commits are reviewed and approved. The API key migration encrypts the stored credential. Customer errors remain generic; detailed upstream failures belong only in protected logs. -[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/09-IMPLEMENTATION.md) +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/09-IMPLEMENTATION.md) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index ec0f07f..a6a7172 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -15,7 +15,7 @@ companion lifecycle. The reconciled extension does not register cleanup, reconciliation, capacity alerts, and scheduler-lag checks are registered from `DynamicPterodactyl::boot()`. -[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/04-EVENTS.md) +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/04-EVENTS.md) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index bd5bc3b..8857737 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -14,14 +14,14 @@ process-private named-memory database and rejects inherited generated URIs in child processes. MySQL/MariaDB tests may use only the explicitly named `paymenter_test` database while `APP_ENV=testing`. -[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php) and -[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/TestDatabaseGuard.php) +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/TestDatabaseGuard.php) **Referenced Files in This Document** - [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) -- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php) - [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) - [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) - [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) @@ -86,7 +86,7 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) - [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) @@ -97,7 +97,7 @@ U --> AC **Section sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) @@ -142,7 +142,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -361,7 +361,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) @@ -383,7 +383,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -425,7 +425,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/17322c63ab4033b10879cc6804a7827c22f92537/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 066c600..23e3783 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBVcsEy5TNHlP/Xz/D/ELaiZcLqVqvsFHZojMIvWXbqtAYqvdZNM8XlBghzpiqWnEov1SV7FQtFPIpj9j/EofU1iDJXVRmqaz5fZFYghM4g6eO9cJ4FK7JsL738Jk9Pp80MZLg8hV/wWALidFrhbh/4LOB+9n+7zkzR2sBNubQpQ8CJCXywcf+P2+Pve3bo4Q2XdnYCEud4sF87/Fh6XF/yl4YV+aVoUDW7tlISB4ZX7+yVhkBU+MHlkjh9Q3wsb82HFvz1GL4gR/pxDMVhhLV6eIIEJvhbXFJ9TfG5Rzkaobf7DkZX6CNWPqRb1vIa1SqQnWSD/KPpeGKRH+B/DFqBZ7eb/hSKBeb14MrTIKWuu4wRF7kOKMIJBVuMYWQrX6NG5oUKP1xUvJjDeerXVq7kG1AlJV1VqD5Da0c4KGBNIMelVdcLVBQOj8hqIM/vlr7KRkfTC1wKtE2Qz5glBCmIymh76+xzX8DCyNNMiLn+wCCGDuPzz3Fzqv8twRVUsvSfg/QLe0aWjgM4Rw+BePhdj3uGonWLcJ5ZvyKyAVlrM7gUoUMBz/KJiAlD4FAsmXPvIbxnPN0ApMDTVbThe14MgVc03fnMupeiO+tlEUSIpFtR5gIoV8ys/O3FZhtCRzI2DUqbXiqgrxSQ57B0nFSTKfuxl/yiBFRzI3+V03TtTUZ7P5Eg+v6wipDcAka3ri8fJWQU2mYgQkevu3K89lDHiaoMoTry8Vyn/wGR5dNvPy4s7hCsI5irNVhNWfZ9r6CqdoAxe2J4b2TbkeUQy7yb2RSbL5neccpDzlTBYIaTUZHvFwYl8dcbit+0GTXs7hFz4wiHKAWbNnjtTbGLFKLDzfBfrjA7TpLB03o+elWdqBN7rPnNy10tZf4EPIa6do65PecZ2hTDlydEJbb4nDOaklaESrjqhGkf165rK7eIbSKEyYHHbPycQhlkSvUdC3MamKUVQutZG46YTPy1ncD3CXhlIbO/VC2L/IZNrJD5WsqK0SaZII5Npo1R2/GM7P9k2hX00M+bo31khxj7QI/QC5uibD2Jx6ziB2BRGTNOYPQudB1IAZk4uvsQ+giuDZ/o4FZvQNqislT7Z4Ow2ji9qRk+lDNq65aguCByiNEEpUpA45EA8ZZypAR2Hkt+UaOq1FhzTcKEFSUbz/oyp8G7IUi1+5cMFfYyYtReYki+9ACci5DyyMrZKqznID2Gyl353hmIAIhcc17jW/QmIIHxFJ10eqs4yjyuISQCDq8b0Vho0FfatTBaV4nsWlecER3pH31ovCsTEBsIGFhDE4s2YD3WIstIMlL80k62Lz77x5HB3xkAkb05Nvq7E0NY+EiJ0KUJqUAST0bIQWxdLUL+Rg9NgCGbUPsl9J3khXYJ+5BcAHRQ2Qn5MJog60AwSaxXT5JM+b7EFXUbPLJBqbsPktU+UevN9OnstD1z6xZ6X4cWXQrV6D4TWM0sUtU8y8QaivnVp4s4iYwLfrA+cEHtwgJ+5PrHPD5FSjswMY2Z7bu7Tgu5Txo1oKSABpv9in19t+HrwN96Ik1yNFe85QpLLF4F+Y5zQZU9ZDYtCg6illkCxGGOBCF0v5SMF69/tkU5KUaEVk90va5y5tKsysiU92Ds3eJkOLf39k8sUJtH0yFu18Jbaw2GDFpO/d/VkB797dJLrLKZOeYFeATUISpwfU06aFMubaqXyblgKy3+S9ki/fVVX5z6ThiXVs35OPUAKrq6ChluTdaPEbFFo0zbPYDpxEsd40/pybI/tgV7fFfXHwW4LUfcIZzS7HZkTqfcpBBLT/5t+cZ+LwSbtzrwc12elLAT4nvgcay1JkLDXREXYcalhltzpxhCrpaPu8qks7zzyy7bTfKGzzzEqAIh9wfb+3ONdQe8aCOFyB6uWxX8OLuuGWsa/vajo4XG7EeUA+z7dLlfPJFmsxkhpMHYScbbjT/SSkhlwZlXowmqqN/3AtHQ+m8TLOJKbdXj3Z+wHVKQQtV3hKuD/X8OW/D4TdgpS0/n9o8Nj8BP3b0qkM","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"17322c63ab4033b10879cc6804a7827c22f92537","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted:qkTEybd9tQzuDstX5IzR1CXs/trJv2Qp8kaORmGdEsjOxLytJAqUuHjP06XJn9y+iXOi9CHh5MccEBo3czEUCbEI3xi3jI2FX0U5Hb1shR6LDZa4SKyGHNVixTBNySA00Nc7Lz+raBGyJ9EnF9lGDKWB1J0M+K73LX1rF7N3R69cErBcAhuvCBd69rsyUTTKSXgEpXu6a6WBUCYLToWdn12p9VWVvjTtcSe6lRUrzgs90/zIfQVq9RYyW/9LbF/T1JjqYM0NGvS+uZhPFi3p2U9QVLIuGWoSFWeMUW7i/mctoN1NLGsU3TIOSauX990uB8YSEC+j3CLEU0RFn/c5OsWoAXtfngYrjb4AGHl2NEDSkwlciQRkxkMYxFEZyYcHT8Gpy9mvFvx8bbUg0Pz6UsIgth+Wt8ksCwhqUfDKRSDFIXTTfvORPKTzfkyLwlHIqFcgDPVkG6zJI8I05IjUlXG5jKJQFuSvTIn3yJqmp7ZhvKQoeYLzB31v5M+ZOkDLxB20IFzyEJJaajhK2ne42xddTRga+uACLExPlaXQ2RJgP7aEh4BxFflfEZTJ34EAFDODWNpg+cS/h15EWTsUaCG4uC1kiMBrOd2ozslPb/B4Edh29LEeX6942jquAGPtDbui9o80AA5R7YrXIWL0yCvKlGIvVQkiQRQKUdaVYNvT3BlqJ9Ka2WMvnXeD93o7uFgQDqkb92et5LlCLAyZL2hhn/HVQ2au4V4WnXgjVYGwqLpihYFplV2o6Ul5PDnwJGD69mAO7aSGG4TBaz1vo7thcxfYaEN8buhL/QRsNVzwqTeN25dxKdYd+zBxU36BMRYfjftV5aUHpmuuyJJkM5VRKQ6BjVw6woeWtQG8FgIoVUuFHpxorMTccI2C1mpkmzgRNMXQ85uoPlKkLHfbtEhYmKBBI5pISQM9VE6ya4qmYS3ZcA4Gby+GuS+2myO7b+pIgX6Gq8Edw5WSPn2Ei//99pnHyVX5UPawG98jbNRlrQs2TtcrBTUT98D4BYcMA+ktxGDZix3F4RcLx5/elIhe124f8f7S+X8phIq7uGTw+ZxP8gQsdLdGaOoF3tin+ZOK0iHk3oIa+E7zaPMUeNmQcixZRtKa4oIeo6dr4zHVltAOiLtV52OQDsPPCU8HwUO9GFXeTYlUMXhErji/Bg7K2iw712B/4pQW0+0M4atRKpXUCf0AstnGoCz8LlV+hEsMY8AS+k7jCk4TW4pv758c4geH+8hGXMLUSEdVybYs2P4Vk4c8nAaIEP6jWukiDhIps/dyb8RExWg5BKcfGJZXTWi3TBQKnGIqc1JgXXJUAOfGwP87PHb9WxxWsvl+13KF6/JUV2RuX8NWSAmST2z9I5whzQnfem7CCc2i5yO6yqpJbPOt+hpYlqFYp/yd6gkodn84E4+o9G2F9NamhIk1rCcqX0YoYhYX3he3rU49QIUaNev/DsEKQc3s+K3yH3L969uk8nvcFIDEREP3Ke/07RicsySihmrgxJ98Ld4lr2V25uD69/exLybGUdn2dDcVBUfI6jWrwipyYCInTV+f2WDOy/ki/Kv/G4WbDZhIXn006l1s0GcFML1GXUTxXmJY0ku4dOxbpkSooJ7fw4n3y6hHWfG8HpJT6bxgFd00CbYoe/b0gzXvAaWW8vpkN1sYSWr1kqeYKUzdSIW57T/K/LOKTHdgZA+L0R1R8CEvL/ecL3GkHaFg+gEYwMpDWhf5rCtDxKebVIATR9aw07hbWczXdZwkDXJlVd5V5vdgORzxjfzO/OFC44ruOlxQSlTZLyulYQFp9dHxHnHSP0L24zQXaZKtefy8cnmOapkooReZ+wZRWiAb7fxmo9D1teGxlOU66NKDFzhuXbd+HpEiPqGRF9y08wPLPou9goHOa/JMQmjgWBUVuQuDbR+a74MSWaZCcIwojBJ/uBzCR1IFP2H+BJDuKSrdeLDMuW5EJu5KRZ0B7R+zFnwOxiZ9EYJTIFO4DXNRb9ZL4JZaZJDqwUUgBM8pWHec/4cM+iRi7hh+rkEMQRAMyGpem2L+oSpr2mWWzpe8wQhlaZeVV2sbybXQ/c1TEtK34eA4FlFqimXo12UKrmimZi1mkAyuF98LXH1wCLNXeJVLWZOMKrSl17JGy+Rgsx9dEnAmdAOt/ePsBXXphzaiSY+6GMqmtIINfcgpsvFLf7VhdP0yeZ+kkaT7kJ6yYu+EvJqw32jYBjw3cBy03f0wLMX/dMHo6VPVsef8AiKqBBoTxb2uWBbY31nXY9EQgRoYajhQYdmKkqEJWTkgXQTwQDHnUdrR69KAqK1wYfDX38GDERT9ibC6fXsUZGq+QgGm8VZHTsFTnVWZUi9EUCA1oH4p8NtjCRKQE1dUmCiF/sMRKwCgiHZ+WmKV4ixhHV51T5RAHQ1fkcqc+hPFcd9uEqHPrwvlORQ9jh5rDbFRNCijsw17TiHm3NlZIZ6TOhCPiPO7135f1/4QfMvhj8NftvFreT17bU7G6ZhUQAvh6EcXhWZ2LDqZR6Buji6hu1u+6WgCFFNo+TSLl+h0xhKxqKlA0H4FQImLcJdXn4MBTrmQhqMe5H1iyxIN8bhT42s42eS/2IJqrvjiLVVNiU9DbRlYBe5TsLfZuC9GQsWYHdHB2KAAAceRlYBlwnnnVPexQl67P/G9sMfPJkJP7aduEQc+ikG8og1weDdx5GYauM8O/D1cxi8/7lTsEtDIGXuCC5OOHBs7utoXRrzgtS/D2kgNytqDqSaHVKaNy8NDlNMYbjHbsr4ffxNCRN6Pv2NPi1RODmwAvliw6D7KLOfoqACJKyBasvMnWyR24InlREQefIeRrWJ37pr9Vq55Q3FhvhZAc8rPO+f3plstLlPFQuqz9RWznCe1tPE0niOz5NHBZI9lhIv8cOJgZRzQJnMNAIPVderB7zfqLtTAiq8aipiVreV2y2vrLz0b9lyC8yWPsQK3aseiv9yw6i9ehl4z/sHroeApfLHdyEscUVNJXOvapP2qTfZ9jk4hocuqydv/duI2D65jyGlk6QuIPkjjMcJ8zaFur7eFq177IRSKIy0XT5XPXjUFSsnXp0ChOnfbgKyNvD71SvzQT7GwZI6hAH67jxNZKymIWPsLwAFOl+M5XOs8X9EnYbxKTReoFUvgerc0IprGMeJ16tH14Yd0i/HHak13ShbBkqSOrBhhWBRCCGt73qsgdMPKqQaZAihM6hzVtV0uacQePDcxX005Zjorr5rGsmt6BTBWli/TnwDZB3Ttch1RUd2LJTCCIf05zCDZAtrx3zbm5Zoti5VWjScQta3sIvXlpHyQkCjB2varsGqAsAM6xbX6bHqsYlZCwlk1uP/VKVdUU65hWydtK0mJCHJsMV/H8ph35q74Pd6y7yvcwg6oKZCuQCA+Cd9TiyAc3Nt+wXdMFlMxobEz1J0fL8o1BKpsKI1yNn3xff0/UITO4WG/FJ3ryJ1ROrErGmcxjYSgvBsYrkhIUJRMx67aSnqHC3oQ7SWeFeJrTuyyrHD99crFg1wWW/Ny7Jkko38NzNnHHArluH3t678lUA+iwYkFUmGoEtS4GEav6aW5hU2cvXiL3Sgog1Eht3LcHBLRR5Bf6n1QOINMP3Japm34G7BaoZ5TNwpgoVoJL4/vUu1ncx7WYfgP8KlUhUAWtI6NFt/vMxjZ9vhCM4Pgn6dQLn/vpc6aYRsyEZChXu0wLqM9O9zLbAQ8qEOA0e42gpKoXjDUYBnNFu0Z5xjiaRu4B0LT64hpm/n8NvjzD3dL/9wv6xCTKdt6T7PmeIUrpxi1OcprTww1m+Op0qyeOzKRfWHQl9S3dREaZ4AXqDFETvCYFD/VJ3U5pXRr93uIH89E9eoGaZQbr31j5m5aYERY2ZXF99fhxPSyd4rranhUy7m67NgGGaNgdqnH/9rR1NPpFb1xUwymj4NoSg+innBL7DfFKsWMHumXC3b+C5jvg3WudMgI0+ODGO6MoYDiERrxIidOP5q8ZN4Jfts8pGffE5/sd8zNMP36qD4t8nF/pskZsgdOVcsUzPmuB86IFlV9bD4eC/RdmJS/lHgmgQ4eTpFRNADPwqz9vkoPtQurxMYLqnrF7LElAIGXC0U6k/oyDz7SKDz27N5B7ryjSs0IVLV2Gy7ZncOKbEyj9CPNXy9vR8rAIDrFLa1QNw+FwYgPu+RoyTDJ9S55NDjpALze3Si28hXfGIoA0HSvM4+r1S8EfRrQmWs1o+qBh1pDKt9hnFpqLjq08Kz/UarsuU/dKAxkzP6FSPHWRYY3YCd6U4lJq9LL12d9FcrgYIz72opWVgWq5BNezdmM5foqsAFgDujPmGbB6YdL7kTyt0rcxMBkjlP56SnD8hLaBG7oTkf4GCzquMcMhaFf1pklIKJi90kufl9CDN0eYHjnF+AzeLf1p/Ruq0IehmliQXA1No4mXjiA2qU1BnmzqTNCyAWN32S+fAkeEfSd+AdD4sMJSSLUhNwaoTQr3qSp9Q0qW2KZGchDCBDXE4mTCyxPNDnHCSvmq+ayDviJacujoKbZNnuuZjgJ5eitj0nuD0S7jD/URAoUq8UAEzo1qq5eziSUw6z38U0v97ZaU0hohyYSgjBAv+umzJOrnY+Wu7SVW/53kYb8GpMhwkgdvQRKZcBEUuR8o2LmYWilmZpKyH08poYLj41wtsUQaVqhgItvECi6G1V1MRg9BzvvHSGxU3jglpZUgzv4dhYrUxabLiVdFRLyAtZ+nx5YSidIxtStPEnWKIR27k0BIsYLP0yO7npcBkx9v7urwM1oh8q6o9mtPT140KgBqUPMRKujN1Qiw0kQ1BM6TddIsUWMS4Jr6oH//jZqDqOM1BgFjEzXhdWWTnwHe8Y1x35EGBfYupFepa8/H/6iB8HUnbLcEg0sS1Hla0OHtaut4N6i/rJNlfBAYjK1tyDv/cwm/bEClj0JzLRWKjf1Ae/1b0LYWIDReal8V5YqrdkB766d1yx+xZ+oU0c2wAn4ij+Do6RRtrV4lTFGs/PNS9CpiYS9yt6xXt+2rFuKuWrDxwLl5krZDJKTvpO0s9aF7jjljsDfcaKJQQTlTkL0h1z/KZxm41bg+KcbsyptkUR/8Xti/fBFOUSBOUd2E0ppEA8/r2pxLlIYaIQb4dYsI3bqvONiFviW9qExQQZ2RYJ9dLDykZiujhQ2nEJQOaCc7e+NViygsPHE0NTb24LIPbnAQX1W1PCt8RtndICZAJI60dVMni+ctjifd/hwY0Llgl7d866veLh6q/YZn2f2qBr6ms+ar6mIrT0zapYhNG+hLWaXxThodnNG02y4Ifd9wFSEkMOqaeMXxCBRquJ8QoH9wSd6nYO3VDChhkPpqdATuWj5/hI5SUtcmDOKTe9FtpP+sSIII8thsMraMi34XovbHYPFdAwrSy7P46GbtrZKTG4gKr3ZtlGIMFlYEPeTPL322mNwjrj92Xtiv99blZVyVShhhNHlHvcFPjXvVWiI3iNMcdDs6Q4ZRSjkLTxVaZcFHL7S6/fj/TeKcISQMVvW/+80GI7791wFpgzGt2UfMHcCakrxgxpldcwlqSTVsMDRMkWaQQzsqaODqL9IZoMYyGJweawPyIFbCanAUfBpoJJUHrPCPVTzsG+5TupSkaxAqSmonKiCcqUA4Ra7rc7B6H67hFyaqzDcQ0HnObKpJp9Z47+70k1bqqE5DzVn9jE/pXNBplDGe2EN1ElmWGZ7ZFl5RSZeNxhCZ90+qOFe0RfYZyk0g7qi0KDnSmIttTqBNXzyktDJhs8cqPvs17y38gAjI9Q2RtR4ShU++7m/id9sSjv3xAHhawuUdS9Pgj+OO554Xezol7Wdn0kx+oTnVEZsOUDtV+8dx9M1X+b3yhEONQZQnpkLzz5trviuVmzgLKxgopFB/Hmh1d+E4KOHkV/SLfy+a1bz2FXqUzu9fX+oRKLKmJJD5Y4sp+/gJSH68oriVKGq+hvF4F/RBmkKMXwE8KTw1LUFl7dMvkMuAKoNnklEyyyVdKit0vtj00CqZhG660jA+5z41hadJqUZ+lK+ITqJjvUrjmKOzQ0q/CIIJETrpCfkjXZmqb4Ebz47DJ16umz/a0IWN/tiFyuwoxzvdGEMGKQ7o8Pd8BciB3LBnFUoHMtR0yW0jxctOzrftPZ/vh0JSHOp6ux72Vh9AZgi5TphCRvcpKlba/I0IyYzkevNboCRgYQP+Ap5rj+93nXiGWTfRk2mSpyLral3GHzhAMgl972OIpcT5/Jm3DX9Rt5xScquys2wJ2dVY8lhiPPr8zMvy0frQL7I5056M0eQjoInwws4fIZtBfEYy+ycrVnZDK6EIc1FdGItERZL7gIhphZ4dcYXtj8cRF6l2PlQ504mB2w/WVH6zE9naxlibeNF1JpvRZ5pKl2Jna35M+axy4dgC7rhji2OIE6pjCle8ZW5yezeopFZ+gelvlQrNqVR8pA6lGoPp/VixuWxbDG0MqAYPN+4+UqdXGvEF5VGcjWCJwfE31XaLZNL1XKfqzBuEAD6R6SuRb4ik9jhKDmCOvYyF2y2jxovEJKGv2qQ04poITEbD9Z/VoGI6qH+Ldfx/pHSxxYj8QfadppQBhfWROJ4HaW65WXESK7kQnLKzIcRk97zLXiBUAfDnoROqbd+VzlfnXGEogSfskcNcyn40WdRAZ9EkO3qWeT8L7eGa70tx0EDmSfkv4EUZhKMKbJwsAyedmc/tmVQyk2CVQCzgBMW5AdHgfkaHRTqiPuRpkSnVVCfi5yUcfdgKeU5eho1iFzrBJ5FWc4LtiU88uOOFewUSqski12Z7xAZDF9QH4eDOcWEIRwy8nzflI0C18Hjz/AVBfeKxfuVf56MJD1M9b5ZyKgXF2uv+2rtOC87aqaGDKkmG36eWMjUpj55xm0OrxhnFYb4io1c7Ar9GHOTCp5d9T8b8AlmDghYu9Q4BS9eu1fC5mk2qntj0gbtITw9yrm94mnFR3epFBM5VimXsIKyfkN6vaxi/VYxLzs/m8P2/iMz5YhDPSpEoE6dtGi+RYFQoGfmf4Kp51MvhxKpBWzIKUZ4oVo3bSR/xTtA8g7m2Cu9TmGyGzoRsGZVWPwenitAOr8BK1F2gZIetevGghmmjb+dsTllfsZSkAVO+a/QWVxiylobFRc/EGg1uQzlL5YM9+6L/vwXg6zBN9kGoGj7BzOCNk1aNyPkub8+YZrb16Nj9GZcHqGJWRlAqG/XekCaEDdi/tUuwHPCTvJpmceD04ErapLgvVI42e6zgSXMnb4xQ8znJCFT/H85Air3ZAMw36GLTdxZbw+csNjB7990zjLDB1/gslSZrLuBFvtO2ciWE7AqYJd4YUlhLF4iLpy5W4Sw50GjAW444Fgp6oVJnQlL0tV8APr2xbLWp9Eo40IOgvMNVPwLP/v39jsXjKT+VrFgPBaEYyxNIKtx8MAUPhCaPKzpEL58BAo4j14o00Ma4zDTGbFWPXFfbTMBZtDjBD7n6z/GJZUFz61giQOlLsQ0APQW//bMxmh8FgqEujhae7IEDDgm98plwNfmKQKAv+nZB6h9iie1nTVLTm5P4ZSw+v3VpETskl9Bq8RT65DPNdkO8pqMBj8J6Xm51FlrR0ErRv/ynI11twA390S1F5cLg+OLAOx271Of6n2wxWTJG/peXEcAVfFaXXlsmvARiKku8WQu3W/38Uulrk1fg3setfivWSWv2nJvb6NLQyqX1aN5B4vMtm3Sx4oi+QCmHpKr4+n92EdLsHfZJa4Ldm49Lqk6CkD6kncpzbtAjIRTVUXcC/P5ujAwgZPyCyhiwkRJnc1ZBJmbF8JianRsBqhnzXpUBlsOObVOdyjLn3rFDaigXy90uf3vyrSJP1LBqN6DjEKFm3qQXpgmEIqfjLN1upGeb3/PrJV6ylEFwbsPv03ZZvlHP6RLo2fOotcZBh/E+EVPvXv5bzjYVWfDbV3wf6qnr5ZX0muxzBkYOnVp2m0mDA5cgkhI8pY8vXhQvMRBPQpqe3OPJmr1HySivFsIWnHbpSKfTYY9BJYLlEP7cQWwboEHAeXdMpmTx1IOUnJAO59nOml+xyOCSwelJo2W/nCTPuEEGkBHLjpogzvEBe7DZ8j4CjYynzKdd8UEVuXCkKvQhDC6HGQhd56b1uxmxh+Aq/w07/nYu1Y60vEk0Mbi2s0Jo5PpcOcG3ZmRXGJf+1csDOpm4wCi+iF84wBewgxdIegpjPTRopBHEPYH1MSRHiBliqdxf9gipweLAX6yLOk/N7H/gqXarYkCdZXxEjpoZauMfawkM7Q/wSjTKV/vi0en76dmnTHOQzAUjGfBEdm3DtJRZd9XNP27syr6nu2mefGeB+q9sHnNOIMkn8+ZBd5aQdVZT/HvT52vWseAb7488OnqKWAXinkPMoOpx151M5Dwh4n5aMVSqD8+cwTnrSlcuBO+tFrxdDhpCjOY4HRq3Bipo8A88g5OJPBxTCX4Ms9FSH21e/YFA14rMyjYfBMSz3rCdSYp1Ni/U4JT4mU5wGxE0/4djSDcJVd69oE4XKftnVrZQuxz1xKObEy3VSf0/4VN+GtRu9PClRTv63n1vWX4R52q3ibpWD1gSnCxUnMGcovNWSM3+syP8G5yZFHgH8sVuthC1LvODHAa1r1w1gzLAWMMQlYzXo0CRruV6bNDGlcp6KZkgbmOZDX1DWXkrz0r1sTmjTSM13SBuBW4EaNJFyvoV5LLW/yNcUDzhhwysPeGF5df01d+svZEAgHYA8Ogf2b0U7Twj3zx8IqyFfuk+q8TA4trDvU5z/fDNnZazo5r526djNB9+vNMRuxziw0qf7cZuJVMHR5+ek9t5JprtGyXisj7a0LNadiSdFxx5hyMW1SStaM64Aj5w9+m1wGu8Mx5eZ4YX6tXpnc6II3+8SQY20Ui9W8niZVOpr4ybqsaaHVGW9Qzxm6UJwSjtgOcWVb6RsO3i6ymooRxQbpZv39tLrxc42g4Vn8hb6x1i3ukKrvtMUvidfbdR15kWYyV1O5PcPXZ3UnMI5fJS8NhsFLE60UNzIga7p36e4W3b+hKghoKnk6JfRtSn7W2dtJgD+pJPhKOxuOLv+fLBT5FwIOHtDzSrdfQrIeiw1FAOmemg6VLbIGiZY86LzBOGzget0EKnLBmMEZip7FK9xIPno1ek3h+EQhg+aDtm//h/VR8Zaz5H2ls6UThDjbVVBw6ffW3Nl71KdgGDk+/D1pvVIc6yfpAgfqt2IYSIjiwJAlvqWZWxR/DkZQUfO0Tjx7fbWp7dssuOrIwo3KQALWFLOBCEljuas4Sw15z2kEQgwquReMhCByUT8vADZMeN1VzAt6X73/ZByCwoVx5rxFjuZkfpXOoxeSCBJtTBCbDlmKHAEb35Fo1yDcQDSk5TlcgrFG12VRpLkHOlZ+fCRn/T49V+TRF0MPlTh2yuJaAl0K93cs1uqqRATX0KsF7XdQOU9FMx8gr7YrImpvgUCheB5XJR1viAxxKCQpaAPpG8SyM1eAbTsNmWsDXz0o9b1h+iz0Pndozebu4NtJLqSXpXCVSsfLlbAaCdHvQ/hb7BEGKf63aL27oNfROm8x35ul6mLX3JWheWr1oPh/KwLgJhOlMPUEDTDMzSp9XpJksZuB4ricLei7rRIn5YE/NWaiswBb5oknS4hicl8YYYRzryUqOdC/7z3GTLXpmFP9eSolf8/Rzt5KNtJQWQK8SoiAbu4e4/ScgM1wzUaNnMNQ0RV4wFAwZ4vvkFNDzVAwpJqWIPaA/MF2cGJOfxA11Ssuxd/2gHXF65fJ1y1sOi10yNWjdnZjjnf8KEdd8ApKjNpMzD2WayEQXzmXXKQ5Ym9FlJb1oIsSJt9Fv2YauH0FlsSO0IWOu7iMPJ/Z0mo5ka31AtBJh9c1gtUxm2xo3t1qhMGnopFozQqeZgiSufSQ3pgrGrUqjwzCsmRZ4qtSOaCu1eDSgR2+DTJ3kSjU9IkiII0G0vFvR0bwL7nOFWBHzs8LT6eQic/CCMCJXuxvvwTknfgrDYIj29BMK5Q/PoMO7JMlG4mfMQ/65QkdmKvVVdmJYl8d6kHjawEtS0JsTwaPFhwNQcXXR4QBFtfZq7hZTyAl0VJ641n3FdiK8YjUJRhRVErBbY8vpSW8Cw5DXTo6rVtbmDM3GHhGWL/EQmL4yVLnmqJloHiCH9lgCZ2spd6WdTbg/G8lS81eFiE3AdnUvL8nOxCVE1cm886d2z5rJL7xXOBfhXiU535UD1FTXOt9IJAGFOrz3q7a7QBcN0mXqjabPSLUzao7SLxzzQ3N5BBtY9E5A6F/JOeJ8k1azGBsbBmHX3gX009gjdyh2FEi4isGWUYmq/ppVDOKRM9TrYBIusyuL1uJnvliLE41KvUnj9cVSGu6Y+LhOShU0oIZzNqlLz1drq9WtJ0pNOBHHcDBUZIHKWkvQu2Kj08LAVuKoqCUTB+bbFSubHE8+P+LqHhU1Efi+bofZdd8IImHxlzSay2TwOJmYr/vg1ttPsxY6QK2cUYrisuDe9flpa6aZ1TDUghwOD3SrGayV0EtJznsqVdhFFrMhyJVUZNqnu/Dacu5QExvHCzFWycNKt5DhsDafNS4OhLlgZofPhh0ORCnb31pkhnfZH2ViomqngfDk3HZYuwW4eKaQuzAskCW9lIk+PGnnNa4MgKye2sy+Bth5Eyn2Y0CHD3wtChNaro+GGoZpaiOyv5qbJLbMO1FfBeD7EGb4VXFQF4VBxnnGV1OFZwDKoa7w7L//On/9Nq4eFY8IJABXL/JWxphpALlAImWxSgoAg837PbDY9dbowRSrVQjhJZUM09BEL2FR+P3kwPwmzE3ReioFgvcAZtTcjzFZs2UHJSk6Mcphkd6ZCr5HIcqgC6GXPa4Aqesw89Uxz9DZfpR7PJkygyZQzn+nGFe9UDOfyqfNF4MxitwhtdniTtmpFTc2JmTNNGNe7IOzYE9kwB52RtLgi79orjTDW5DZ5TnJIqM3sbis0VBgUGXb5JY7oVpXPDmp5XByCkb2voab6P4uFhT8C7FmtsJVQyPRlddFGilUPX+V+n+ANkBMUhuMdowRyKwSxfaNsDVSgdTuGpOw0N2qr8kDOM3NDaCSUXNLoaxxW0NPdO7C7gFI4vcdYhiHy5lLmxuJD62giIjMqQOxH5cefdO8+eiMemWEBA8NQ83eQD+SCHuzLgo7LoIvZmzskylMbYFIwEIzAcy99HjGicmpxKzHFHyN+CRurnuNxaaMqx6/iNmvXjrftA21yI9Yq9T3Yip/33ksWdy3c7IGe+PI0WYExvJ9c/lBmMd6SGu8mKYF/pMxVOATbR5+xtU9EPvTKfOM7TmG9K0faNj7RxdZdua6eui6PekC3iqcWyGt3EGe5j/do2IYobTVDKKhnMZnSgEOmx1rTBo2KKbY4mYB+RtNvMhRJW4StmcRz8tPcGwZbrgTCjL+D6d5oxRiiZo29zSKfQ/yxmLwBPZi4v6LgZGpCMGcUqSSH96k7eBtSoifW31yPc40wPMNsgRBozhjEagoHnrFGA8uxx1turvhD+04CaMdCQGjZ6icqM9PZrL+N0vjxFN7feMPCHySBixzE/k0gwDf7hpMwZnkWoBwF16bK8pNYxmME9DrFDMG1ZVELOxH1PqMzOqDTB0uv/9si0Y/5PfxIk1H0BbpxVOacW9gDfuwaxVnRYlTl6JDYgDqDuXSAokO8ldVhABFE5RQdKb1J4nx2I7VDmS811kQTLZlZZ6jdvLDKKVq/yvnk4j2rXW6cC1j8cJ140GxQXkK1EYNUV80o8Zix7dY7gJMoKBsCA9hXFD9nexFfhUNHwcjYNhR20syWFFJehOjNJIcRPibYc15Zz5AqnBLYgnqo78xogpUJYMsClJ4ZMBWfGSuoWWio9OqVU3LHKfcvBEU6TD3xWTr225Cw6UVNB8c2OqwIA7Q6a+t/mvH1EKysRXxsk8iOTZ6b0PM66iEtEt9tDBAPzCWrAY4c0tCHRFXyq1UuK7lRWVaEnrNlpoFW08Q3zpt1nUR/chEBfQNOITrI8/imqT+CMvM+0hhtK6aokFYHxdOXeFRDOoGeH0/qfVCAnxv/XLz3ZS1+qeivmj6QmjR+3sKYPAMRv9H+YzvZ+ujz2VW59RyMTJaZswXzBmdwYfL8dSxo7tgxp1B0kJiKMfPaTWty3zszKcCc72NXo+hhErdqfA03QPD/w0kYChY+rX321xwuVFltMhDKwG/b4N9mDi5be+8lpEMlQsguMMFUPwJRtiHK+COc2fvo9hujDwtxhvv9KHE3rouXBsqhqVzezXbnSCJRRQg++FNw0pApZIaiBJsa/oIG5PtnyPFCNSfIo9ua1/gp2lt+Y5ipU8AXJTf2RbmbykJqlGUUo45aqA3kHtH++PNVDlbJAwX29qRziiS1OtvUQw4ld30U5+phiaaVP/Zq9GOs0KT0bernuZcmtau2dv27jESU3l4ipL6yaBpqzRfwWluAJhVizirM9O6Ao87LEahalzvTjnml95d+SCjmf0G7HMSGPY3KMiZUoyeOZ94XSMYssRKNnkx3mzxJjPuH7NCW/x0HsUxFLsnDYBl0xtYGKYpIAJoMIzCndZaD3FtRj9AwzhDNe0bsI/BwQ3GizTyr1TGCdXKCy+NaIB+5/E5vfp+1Atqey0P8Ak7ehDSNvs0NwAItMjNWrnKEIBVg7VYs73s8nuf2rXF4uZAbXAoSuljxhpe63JM7roasaBHvCA11M2/rw+vvLgBuLUjdGSbjz245MQBTwuruVCg27RyNT8kyCtDzqJeXC5z1WSLGUUxmd2YN9tJ6/Iasx44EILMV6qJbkfJq2VmcKO/w40/KM8VqOHuZLTQIf8jGWgn6bwgady20kUobrKVMR5/vX2CH8yBxBXtjCmfPede3G74VSjUB3afEelgGPcDQlLia1r0M1Fh9eMQUyQm1zUht6iHGBBfhA0wh3fF2wRVDrMDe0+0nNqknX3VT1GrKm3sZ83xTirO5NNmKXt1SCvF9hpueC718ZnJvfF8o0n29mep33pAy62WtTkR+aMcBEsaDNGqbXfXB6SSg6eDcpc0AaUkawDlnnbPOm3/HVPjpNVngtEy94+cVBDJ9c8ceeBVGj6gcKE2RZYKRLAzxGshUKstkT4aO8i28lAH2rPazurAlVOuVkcJOfXKMMREeoU468NNBQti1Iom7il+PAxKMgRmvgJ24aV+5kSOm6oFyATQE/RAhp1TXP2jWfDhgGlXptbU+Qf11TTOCKYfTmiSVBSwwLZuCxUhEH9NxVCWBHi+OTeuecoa+L6Ma+AZhfFwi9sKOOUsQG0BT9ZApCeg6o4m0XhqXu34iYHlNxowbrnkXKrN7mPzilOALDqGnJSX4hLsSHKT4INypfPH9qanWiFAqnmJ3/E968Jk5ZSa7hRbm4OUL1W0tpfYlsHDeVnANkwLsWBd3PLIe48S/qhzNzmDgFF1Py8fHc5Jp769j2WlTgoponm/1y0YsyBI/ywxaIy1y6fVjKqJC5HqQVjkLs+SrwIFDFUEQ1dzTAbhd5+rEtvz+jgpTGvFpE/7FHohc3iRLx8F6CcVXffFFDZmRcs0VPqmOyJwdVd0x0NECEoTHBvYqrpV3+j+RAkibPFt+7ultMeBxwZY0NQ47GJafHRAg6Y+RiOw2pPUqVRjeiP9lUuAJfH5ACz7iFZ1cIr4zMt9ZSdrdb7kjw/D3JBtVPk95Y4J/iMef6MFf/qMmbf3JhC16y6BnOr0T7rw66NlaD4zpR8jIOHFErzAhJltsxcHmcHA9GoAEAjq76dHMQ6XrJfC5zKlwLLlmndHniu1CKDCQ4PXqqhMn8Fi37/tMV9fhJ3OXliNa3ZV9gBDYZ9M9MYwGE/j5cIK/tpIK1PFdhX6rI9e+MS2rjVuWh5/2vFVrI3WvzFuOVNywdB4JC137UEqxYIaZW7Q1MI/ZrhkLuAN1UUBaEzFopW4Mc3MTK2uSmTa4a8rinCM2ZbWCQQjgGgyhkN0bnrXlVtHeznx/HTGFQQtArTVtVygtTg6+GpvDEQgl2PM4eU0GOe8NuyTPROjOGNh96apt3l+9Egxu6JEY8yl0Wq97Y2GDmk16/Ki0SH/OwA34vSHFxsdFHUkHWHuAqI9V0JL8yZoNW0YASL+w26rbf2Ldm5GHq8XKyIyPoDeLpdgGT32Mf1XqKOFlj/DBbCfQx5ZFC/ifuclNbJa4nGorT/zaiFNoj1AZWBAzik56ysnfp3dGj6XEfJfcftQ+jEeXXwyAPD7XvVI/uXQ7rdKW+ZC3lzKQMvVCQDCn3QRKfQADXkXNFK66y/RLZiPg9aFBKLA/9dDIBa1mLsRgk0pQyqCCfrrL5Tur0eKPM/JFAg5wqYtpHl0wc2zAul8hDfIQI8UEFaDaySgOcSmD9hVJ1d9Ju6Q6Jlu8xwvorK/UeYQDjZ/vkzzzxbvJxILXsLqcnInl7WTswak5kRwvmg8BKKkxo8YQvTp9c1bIwtH3aKLSKTAYDNqSQPv3YZVthoOxfNs3EQRJn9VKa0uZ19E2nHl5FnbrUzl3thPnl662rhNbKBRRWfrOuiLwKx0MzsCdqIoQNhJcFjUZh5KRjWzRVPeIdoiTc4un9yzjbcFu1/bdt7Dd7q4vp9CJlYb8kFHY0KZH2/AF7LLGUYLuL68uh4kKdbw3k83zMwQO3MFRiV4cm7uCNsz0JZmFmYh/+uk0ZFY7CMX+ZkAEpoiT3tLGOVr9ILS8n1dowYK0+PF6t+QWBICSrvkjYRTPEKrQIEsmUVX893EvbQfSMX1h2W7U1XXwcbP6rV1pWhPtmoX6HfKREigcgRvf3EeUOQ0pOMQhVo+lXmhRkcHqsDVF5J6bf0xZ0QTgDEEznQVb/7TUWuhUzTH+yPme9yKYzu7NWPwyoTXA8aNlcxuXLiGHytrfxS5tjcdj2YpmWed2a/uoHeTyBrIMwnwNE/39vsEeOK4CFmdRXoFimwIBhyRJ1QZtdxBimAwCq1xkfF+zZuEOgCsHZRBFP+0gvHBHJg29HoM0/A3p8RrucfFXzylTzr26zUFmUezCi1kIHF/3se+SjhV1D2lhHdVp4hAY9O6AeBFBmwfWByV2vr23g3UJBB22YqKoJG6tA+2QHax2IXY4c7CHdzxVdUZCXUlEGJsxOuhU8NgLEvk//U0+AkflbRxxTFHQnMRnXAJouv81utGIYGIkHdCIz7eSVJMV+YWLsFU76A23y6d7u2L+zvd8Tb3kxYaA35U9kNZbbd4NeGHR6rCnYnx9ufaxo8LDSAqWsH8GRkfxqtND7VNQMK4Fh/iTLXV6aMf/v0XH3EecB99f39Mf6uWhUyNPQlIMHhG30ZzHnXw32HGWgkhkyITbSg9V1FERN7ohQW8A9tFv8OuNRZps1es95IGw1pisq42NF9CCXKBY2t5i/VS06sB5h+tkYSf5VGkq3mb6rO/AZLxqDNNSJ7KCszpyYXzOu+4yhTwy4k9A2a47CwiTzLGgRyQb06tQNY2AEpoVVNuIVygbv3e9CcZjv6ErSAfGJNuBqhHG6Kphor4JZrJmTEq0lWunte3KAXpRHjr1QwP9vym8HiMN2HKuJjFJw5+ziwZtrBhl2hk6IYac3RFXsDvn/oyBipd2mBa3Rez4l1x+vc8w8jEIYT5gDHSOyO7ufnLrGfrM3iKDAujCdFzJUshJgoCY/ryuLLieqmdWqDz2xH1fg/2t2mWzg0BViENG0bf7NdzG7qzH6y6xrHFv4uwvKqloEdyetwT2WgvcY6/U8CQIbbrEW1bYojYszxUQAnb527OsTSZMqDLxCEXoQ4/GeGceaLqw0EAHYplDC9pF3xNjXbAiW1VY6WKNFtl3Ml6/2qAL6GzPLYoMFWgR1v+fhnX6vlJWxrGt7VWiqpvWUKfzyssfud13LNxcwx4sJVz8ejK7jgv77Qo8CHm2pJgf4UWOFL+GybX55euGZeqDc6vYeDV/dzBD9phAvSE9xQqYGNXv/dEFxddPxtdHiDeFULEekiLa2svfD9qjqWOO9SA9UgIxb7ZORqZK5JWaiDjUg5tvC8EbLyX558cyChLgvliXcO/X9MdECYBpMWjyHBGIleEtTyczt3UjcBXJJroTRAVhWDPDppn+RJHuv5Cd7dccCbbOJO7EzoI4A+XyA/sYLoOxyDDVvI7oglQ9wQbyhiDZIy5KLJc75IKKwRqsllIS60gv5a53PuQ3UBnZIYCEGhiCCTLNAzqL7aZlmigdoHFfCnKrg7QDF/OP2YUH2NOMJa2mh1uutZgsqjqXIKqlURm7E998QOG4iwHd+576/UTHoa4UyzwN3jWoG+8Rt1lpuyqiRckEfr/vB3W0hrKHL+T+rcWwVtbc3dU4Rx5hsHoSJxOzTfnAyBAJStVRtm8qivv4LWBjyPe14bZ4+BYfPGiBNdT7m2d5M6c4CtiqNovfmdLTuAEQmZmdcFEPnT8cFSeDp/cuZw4D6c+n9knCFj4T3ukaI5cuIm09GzHti1B5zCr5mGukDRsjxDcAcd4OYjpLFmtaHJf47VQ4YgJbhdDyl6BAKrCqk3nHbUTnMDS/1mChN/NSqmznLzYns7tlrm6Nwp+xSz+X+Hm3FnPd40zDpiCpIGoEq30DT7JITtr25lIy/po7lqbrEBZuhuNL8vz/k2hh8d/bYxjCbJaYBASN7maVeg/wjdrVPJm5oW3ODnsoOw9pT4XQoTVp7YdfFuKGIEnphrIjCMzO8vIvwAAnHZlQ6qU+FMTjuqBgaiD+U/4RJCtrvgcUsQtW1+xeilQk4nwOuJ9dd0mtSW+2YX27tF2RrTX7Wye8GZfUBfUzAOOj/NbZYdce/LWClXdTUFpyHMH673BhCZVfFpdwKifOnDk96rclbzRJfBT7lzIYqdSyZxk21hi3j/iu9uZimdops2rzxlvqYd2PYOfRMfAM2zzqICyGF6nsh9belAWjnHce4hkGcPY0p1xFoIN+RJOUflg6k86nPpLeCuSWDkBdq87uv+ANQHhOOVqpZZNLvfsSlvdU0dP79iVGgbqZ06SQnz7Hdd0elReNH8cMm17OUHhbLlNCWBsOi4EtSgBIaCXVHo+59K1zhsTN6xScR1A/9UDl6ToSOfutFHR3dGSriRUnpYloGzyB74ozqPKVMrA9YdVV1cCTzVvGLJWpfHGPkCy0DxTsBNK0MYxWXDFzTKO3ZwUZlHZj20UEqHe3O6tg2AgME72UFOT9aPZ/errTwDVKip8OLh+9O2ZHh56oN27fLEDBqBTGiLBdfmkxbeskBq5iY38ZoCoGp7Zlirkxk7IDcKxnh2bf4WG37FBgkYtCVN7AR8h8lOsvwLurXX9mvczxW3kO8usWT6SBOH3rwk1qZBD2oJHWJIHnDKVljh9lnmNdMW7DY9m/3rqbSU1X/qmgUDLcScbWQboRIJiSL9ruDLFOdi65Qc6pn54Utr2YOQpqm3Va6SNgQIytMC+DsB9MubUqJe2wMKruIVQ0/A6XkC6S6benIZmuoSyWm2fKolo7iWLcw0aQG9qAY8hTXWzd5DhR0IglH12+KwiQSzFBeKhmQ6OfdtZYBlU7TA2pcdGCdXqoadOOko8T8y5qwGwHZsxdgGhhEqgXx0tm52V1/T93rn97CbPpbIBLDkcmwHL9Sb3r9nd1dXJ8VTNKQMrFfGXrmWk/Q3yToZXDyb07bxCInVMF8PMP/4/o4sKPM5rp5uahwxfdOVDsI9Npyzv+fdtLf87DwSeszdGmVPElV8QFF8F8rGxC1BBUqYoIAON9Rkb0pvmNJU1QunkYJHwB1Qf2F0kIF4RTcZzUv8txKsMmNNsTOyk/YQCAm4OdHUjYOh2Iw/Cp39e8vOtB7rl8+/hyLhDaONbIf2hqHI31CHSewz0B5iZYEp8KXdnX6nH9JjrRfGTWKCC0gtYbquHDbNICzwf6QjHB45+k3x4RCUxORGbZ7dozhUrSWQ4/pyM4WSNLUaxi6Kr6ThwdfARDPrc7CZZJlcCf2dBsFGfMMq4kCtWwbMWQnAikrP9epFgicqaRSvyD6tRALfEsiMamc7qGL8IAA/RwBLrADGtXRjBCNhPo/XjNyi15UD/RxZqnY0WUzRccpkoI1Y9m7q4XDrU+kBhcRDwFd1dr5UimjTQ5YBNfOWZm7fQqvNSp3Ke68cKr9coPSRfFME8iJU7murKo5Y7Wc8Hqdm0qXb02FI64e5BudV1fCoRsBusMlhaFAsGkZr3hP+o+0c4/chRVTX/CYN0eQI2FrYCatrV9jLs5U+M2qw/L27IHdAMDUyeyZBqSM15S5LuPQoUouzvL1Q/wE+pDGFdjaqmnsaACkryWJFEvMrf40Ofu9ts8x9J/vBirnWDJJa6N3OualPCrhL8atPPtuq0rUgGAk0KzX7Lv7DLtbH3sQ89Xk6+rImJZO2s3J/RKFafY5fHN7tTsSOEGMtocrp2JzuqqxsoVmS4CY/nZYZUTsnNeLeBEuntE/xTcYyu3pC0UQDaP1o77Re1PHmjLB6wDGMPBnMC+V0+dEa7xq4LhjnR1t1pF/iKfLsQ2xxGeySQcJNb1veHgeRWiXRimiLuKl23l2oQzTqYfGAtw5u8+nyksWWY4fyQBFZ2DGKY7YVa/7/42B+PsYJkv7Cnqxfig6L/p0Gom2pRlQAllbkCSXbcWJxrw9yTYPW9DF6nlBd94K/xdyOknqY++bRKnENbYKf9uCr+v990BZuew1LqGyp1n3HMe/V1SXa0JP8QQPjx/w6Zt61hZFfu0PTMWiFxFXylu2Xa73Q6iN20DR+RYWCYQzpmUFOddl+fXxzgQA1ADpAjyqpg0vxQjWUU1izYkKZvxFlrhcqTBlbwgHaI2ciVZJxoJ3513RpGkyskPPebqzs2vlPL2d/nGOn03hq+iNxTDb+iLVTxO3fVxV1qV1SLC+aYIe918c7fF5EzaaOIKVqo70Pa3njEMFwI2IQWKydtrV3121YQC+h0n3C9TaJaxr2leQJfLE/WkH7k8qqUnsr1V8eiPNYewHFoZpvy3ok553HCWLSZUrFNPkrjU/3AS+W08BReYDGVQzDg4eZPYwCmNSb4j31wzegAzO9YouZuikHz1VGz+g0qPKBcPjTvYtM0BFj+Ox/rGdtLk0dNXkLfBGAhlSz1kLaEcox4zlKzcSUPpVQ2u8sPp44B+H5aRzH3om5OHoCUcDADbHD/Cs1dFXN/bydIklSH3BoZ41zuAiGrNvGdSGlcJKeoHPsxQIvSFqnaN6pO9VObYkzGVRoZyaPxu5f3RFIvnDIybqJbU+MmhYAywHLXNOfxjzbh7N8IC03TenmCicLAO85xOSBNhYpGT61FVhjFaCbh9TWs/AATaR+g3pbyaxxjzIG2SvvepbXKi44AR/Ym3FqGsvHG7KtrxpctfTgsv01z4d8FEpqT8AL1I/noqEANcb6nEJUYnKlKZdXYbU2Q4JcFN3jg24EnMsBBaOSxZANTClPYWO2YF8QjkSgtkEpiwRkYI3CF/S1PG9+a0nz1iNIRRb6AJ9zjNDBAloXYadDKIBhQJSzo8lz7ngG8xV7CMeeO3lKBKj0njPi+4wdHWTc0/hgHAm+yThEPMdlUeIZWDBeGvhVXF9b2bxbfF+2i3hOz81i5uf5/m3vCilVVXDDFnECOTAi4SN0lV8jXy0n06QCH187BObk4pOkkRffoWR41D1e4XDrPpokH5gHhLFtT4qjHitwWz/EfxrwNSHaYktnLKJXmmC/WfwvSXBpKMUt4lw3QnFT1YR/svW29p+M/MKHNQNVwUSIKnjphRoFRkTe005ye5RC4mopIet+6Jmini7o9fXPqLKI7LskaKPCnD/V5kap/OsSIeDF9cx0FZnuax8MfG2xTksJgrDw50pgoJAEpyNtYTTWbKW7u3xzYn1TltVqDVzaYlZEpv/3RGozuYJAlbk/S8los7dF1cMhfvBubGrXD45UxMvP90udKq03isSWr7PqYH6/I82GBi2PALgLuOU5GhsCmtvhlFTdTxt9f0C9mvGE0K7tVC46vRaTRrej90EDbnJnwzYsRlcmewd6/rIH+m1uklCPLo2sWrysJ/PYbwXBnJwucXCq8oRp6qoC/37GTXaqYAc5Sn6XNa3vnoAAIvY+L/xUqpHC0mPUgSXWDxWr3UzmzHIcmjzuDIX7OKOZbv1L9rEzt8YUip+1FbKCoDJCzxtAToEgrIbE9Zg1VZnFfdIfe1NdMnB9rSrUDUvsL/vcq+P46Wx+VUG+Jm8b3PeH9y3ssy8Dnw/VynsZlmqxKtnefBjC87epQGZ3twjgMeB9vPui1Chbg+nLTBzCaFxOSH/NX0Eh9iI472zPQxwk0u28ZDEFJ8TbVZBBHot7MhYnDXihieqn4lrnVXZPfxD6uN1s2oYbKxRPK+5pPuQzfrouO0HEZcYJZsdl3youilvDPO5n6zwJMA3t4FQ2S03/o1StOtnb4JxfIJu+e4kaflH3bTkXcGe59p4nzqic5TJemCJsp9kWKx3WM2NHpJQnLQjBrhe4nDsFAJt6zRkR+BYWFmfzkfBBBFjrLrZmZxjhAop0WQ3dqZ+WGE6xl/pelKEE3Pk4yti9n/uvHdsp6h6VhBUQ7Xz9X0BFYmUwLY6rOJymYOycHHyxX5iTiHKD+qQHf/gwv4EqIAzr3VKGC0wYCTQsQNuf3K8orcYnmT47vFlOJ95EzfIMvTaXQNhOC9VvB5JNGSbbA4/VsCrD8qoTK0iQeKuFl3J9Yhfr2btBX/f4A0UyfYHNSz3ta+6QAe6O97Ne6ORcuwFHnVYuiyidSHKSAJn0UrLwIEwOk70tYSafIEaX5KT/1aT3KXNFbl5UyzSEAFBMD/CCPzM9imej/VxXQdY9BHTLp0Z8zoTOI0wjPDbVVf9yiE0si5t5UUFOXgcqvvkxYpxD+TT6Pkn4HceY9WrwbbypLzoWm2QR3cl3If+XqFsaANChpAIxtWnchMa3wYICXNl6SIUPgdffF3+EoVfp/HfpfBHcPiHIPPNLmZ/i7B6HGpZUycV3gnorIVivYZsaDTcDX+BIuJk8vt3VUkIuoyi93JWpE1j03JoB10PTzh2F+YhTmvYVjZ1yK7URrTV34Keqgdbi1G9Lo5urqD6YnRByZwsVHMI68Q12/gF4oxChR0QBPcZRHVYQ3YRKD8ZwfbkEtDHWbKBLIWJ0pTuhfIoXamdfdjPRrUIY1+ZH26Bws9IZJlQXzhHLtLNIxB5J5eyvQRSgQOPiV6lDzHZbeDkciay1oJd7pn9vz4zwPnohHus193QNfeVpY6oUjHYzAIJUGqNLVOXbY8JppoREG2uo3vK+pDI55RAa/Uf7747fqpupRxhYw32G94S6CtG5+rVInikmv4ArQ63JXH/DOvsqcqJZU6JLUN/3GGj37YTb6bdbi0Fj+NswEf9uMlueqfasbe2G7oaKuVuHW7k/YgrxWXsTILL3N/sd64g7fuxFimqTj8/akjv7gbDQX2TjBMcTb27FFG5grYO1IVGqnRJbWl+NoF6Aek3UwMcVuFrlUN4DCjEgVPYKSbZNC4oVcVWxS0h7+QKLpNiqT9RsjnsgYsKP9+FgvE9QYM34AgnVQcUOfXa+3yIauN/1QL1v+bc3iNcGKs5QAlNWU22E0WI+t0BapQZ0D/1vxgihHfVE5Xbni1mVV6MvTwkGF0V9IEAJ6Ylwx9ibUEiw0FOK45Lov1jrEqEcCg4+zYKL/OaFxuEwpBfgTXY+jzfy9NV9ArmK82AxABvg1oCe3BEcpEzAl6M+TZVjECFLG2xLFur3XvdV56OJlBSIKs+IyYnTST3otnvKhDYsutjMFx+DT4LUciFPRdLqDmpn8BqSxynAsQ+PM+0rXXoY4GPWcTaeEC0PUBdztcHhC9GGY9hRaYuRrbRvBpWIxieHq0zFJ4GXHgCEAEVSYWJwBYtKDN0Nt10brwB0jQsYTpZ/FDgI2VxOegjA5XWBmYqJaNAXuukGdX31lruJT6x6xzAx13suYiyGwlQwGMJFD2n7virZ4GC08lc5T4Z3eesZ0gonXL+myfXt2FBO+i5GPtsdlJzK4uXAClU8zdEev16HGhiQnbGVyhQ9V5Jq5DCKp0AfaWci2sO/6JAuK/uxqL+7UdadrCogXVgY+ZB4AkPYybjT5srsQWaLrmcK99aq+Cx+Qgp7qOOON+I4ZdYC3s8hHUQqo15R8DoKKIl96ATC0y+UNGHb7QIvzRIEZeYj9RChDj8M7mEHS9MB9pRM49BkAi1njDTDY6cIEWMrGReeiq6P6kmSnfj0zJVSRQGzzL0Yimb8QPYIzCkNZLemCGKEZG8FWfSmgLxFIXwNSn+3Hq8go5Qk+INr6Fsdi9g9OObotKHA5ywQ3nYeEebFSQ9i5hO6fJMuLAyFtIc4EGBHIiE4NHn2TYpQA8I+H7RDwl9FxhpJAgmU8nXyM8pq/d+KWBkPJFA0ltn7BsYx2z/Abv7119YbmBNvCsQ+hoBsSPVIlF18Y4T+d33bt3cIQP0u0MI+2/vw8YWXKCNX58JxeVjM5HyfaaTOfjXOJKfoWzmknkfqPwoKXfHd8BeUZh8nauh4Phe69WYMTJHo57uoxT6ty0JcsUWEpzgUI5mgzO4voUUMdl50X+urGkO1eSqb5+Tj/gBsawEuGxqop8az+e+ZGSpNRSxXxBgjZKJ5o1c6KaCJmfNUmt2e/ilXFCsu636jfXU1uoAnuOnLNHzXWEXu3qbDo5JD+FZ3AreMF0+9ymVdOHOweRp3vwTNTxdItpISglbehh/HkcwZsoALGQKs1B1TJOuNC/6386m5L7tVjNYUN16OglnTkNfd7P/PWJvTND1OXgn19RuyIG67cr0/Z3a44VVVeAmgO2DywCBdFphadzFqManWDg3im1wbCtT9aabrv5tZjaNB8Axgu2yhuPJodEl6ouDf9r1FbIm4AxiIYHc2eKcdcXmaOKObu0uWx9oXfVKGB7wz4N4hwWPC1MoUD7xBtEsTrUjUVstDBcIgQdqJFmuismaXDyHbGrsDsPwq7fvW89rBAwAFFl+X4c43aFY8QdC9Uiwn/w8jTM/AEJOsbase3LTmKH12U1qMuzN0jd7URhhUhoz3wTDKstmiU7ybwvj06TX9C01pBZ7o2mjVEx70QdaRs3DFC/tVnBGuWLcr/UI/r/mR003koQGYlX67oKPcgLOdYmr02RMvhlsdqcNimkrRts9KDPcH5kCq3FaTTBHSwM7DKosPNfLpemIKG6oi7Mm1dNCj/bvIUe48mWVIsmFrVB/kTMW2SS6swO1WKjRSfYgPO1ZXmQeC0u+GkmbuCuCL78gK3Ac4Y59nnZonoKOMt5bp7i9atiiuUolSDA0q4+uA7d33HKRuokxTfUxkg8nDP6cpgqRi2P4RXCDEPxqCZ9M9W3M5ng+nnDMZOmWhySvtBDVMPSC7bcxIWU3qk2S8Cnm8nSL33RfMJ+RuiMRDtGJx6l3170dHfegAOke0cwT1z3i13wt7yo34PTCcRvcXsAXFjNb1fpeljcQbSjmWj9mlMSZLXe8BMTerF98kF9o6uc25/DqyqoMA8MDPkR7w/1mQOLcqX969DIn/hFWHlAQ5g13SSESFsPcvMfyPG8FFaX272I90QQUv8HyO0d206i2vl9tXFi/y1hMhlUZy/sMAWhPE9utNSk0RoqZqfkHFvwsPVW8eKY3CdrhPscjFQ1Rx6sPk+hJS5BQR5LB8hYRoErgTuZUy+0oAr/KDW7uYYN/NsRIiVjC2LJ81Au29N5WKjSMZxv0oSp7v05FLv9mIfeAocPkMRydWRVSdWo29hCLeE0Q/aBgMOFOs+N3Ywsg+TEetMGiLpNuVLNHPuyjUDxvB9f6SlVB7IGKmTtjvDqUXjMn7Uskkiquvr6LIaudK+zk7YPOCwxf1bx6S29ONO8p+WdtUFWMK8tXrcQ7lG6Nk3aECYR0XrMThokSxReBZyXoD9f/SJ31qna9Irp4AglFgT0hSivOTKUP86J4e3RATWUftJfsTlsObd7SHlqoGKf1Whb1wNa7ZJSTLAvw8LVQlsTIDRjfs+LvyJUp/l97iuHFBlBJ/sToeAPaWxfRHvwkkDP0YNAqfa+8rAVtX3LteR/437Be2Dh1sOAwH+y2p3H8lwH8MhikSwQrnuhrXLb+93YJIsI6aYZpkUW0cOmsijblV16mVEInsOomkiYI4ZExN+yK6oKgfHqnKmigS6Y7TQYY5DifbY9E7BJkp4Bm3rctqiYgibl7fOCpxT4INNJUBp+BYO0lGaGZC1H5ybdC8RxdSx14TrMJwV/k58E91IZ8MC/Ds8jSZHp0dgyMZetyvc+l13fw+Kj9sx0eFw/P7ROZR5t+b5KY6S9wFHHCReoHzDABePo8jLwzjeLiS3fdk5Eqtp1SUDSKZ1Ii81q8VjjKTBqHLJeDP9nFFkIhbY8C71wAU7MPb3sShnD9TX6QjLE+OLd85ntm1DGd7LNMN5YB4p8FgcsDOziz0KuuKBOg/nzOz1dw9Bz0ICD8TQDQYRLJgazOPLT95v+RZfPB7gK9KmJAa9wfhnUOCFCChnjSvkWQWKwBiHGuj0kc0X0UWkkeWgjJeL2fmvnBA52w+BER+Vj05FfNJnlG6zjqkoC4WlUzMiF9woWoymCsFBQPVDdZY4nqkWfElH4YLASYxuaDDn8gh5+Zpr/tUXCbhVrevjX/WYIuB2jLOV+A7PZv3iU/lvvXpNIAa9mk+C+C3XVXPXmo/Afi4gC5tVwGOXN8OVjzxpIZF8UiN4kiF/RVmLuxPwP4Vd/YGgAVbX3VMOCrqaAMZ8rnU7+F9BK6wsBSerWy9aa7kWQ9Ht2RFFrXN7mbEgogOtGwdlmbNK0cn+X8Ftv21olaUnDB7ZXBbuhStT756G7yoIdhQ4XMVgKcsFzcG40MXNlzx6htnCZpI/8WYVnSnkEwQt3/+03adsveSJH1DOZanvwCbLKureUXrkRuiSpIhY8uOhdInkcQk0QN6DJ7iqrDItMaNn24FYLQqdFNVXvu6XVYwwW+mGtxtr0I5BfGJTlpyk9EMMD8o6lbohN8Vtbdu8w4C2zkZsC3Jd3cONJ7AXjRj1vtsmYJ90iTMw9qhs7Yz50Qyt5gOQ91oeZsmmCVXF5YQlSlH8ZTxLSWmeZeOO0IzbNprezfOuvOFqSbDhWFtzhP/oQWTqdZ60THeY7tjFIY+qEJsFUEzpDenrVBRL6KMhjdANZLr/J60nF18P0VyFcHCvlUu8C8wfY6JCHYES5sxt8st//5DVdRIuJtwhkNoC0MxIGa9wet/5xKf1VslJvGNEe9FTRGfLGqHFCSnRlCM5/0Kow5FwSvvEfjleHWbaREAyuiXi5u2Zjovx3vGBQXGXxjZ/w0Kr0fc1io59DqEiIX/+hdcYiNKmlPaoCr+xGxVUPqtXI+hugA0nNLzAi2onq5r0D8gxQJ86w/6QXUgIZvFD+mBd2Yv1yict+ItE217W9laUYXQliSaln0CYTfjyAOpM5ICDFDl0kAQmZV0tDuFmqiXgxIPk8jk64VhjWbHd0iOc2FXFPySGFC9olVDuW6yYE4MD+OZdhb7ihPYQfXqZU/Ej85B+Q+ih0TUwWxVoZbl1F3wPKt3TPhCfRy32WQrql5gGU6rUz0TwdW4hySAlu+18/LLdHCJzlc8Zly7nbLCSUO8+tAY8PI8ajZkKHAyWCkvAoxsMZcs1P3HaCI/57iL03pm+KwX9E56FyUgI7c/7CmmR+vkH1n9UHQHJHq9Bjkdb72G2GU+gxA/O+G67rSGtIlAAb7c7g8aZUY/pgHuG07kMCvKPSyv8lCWiaGb1cj4+MnDRBKE9EAD3K293mQOmLyxVwXeBs0hbfh0HxtEqkb+1hC9p47/LpzVoHX4JR0ADMGKdLTCaRvWytHdt74a1Kxno+bKOJRdyVh9GfFsJIulpVxoo0lbnQiB0DHMZRhDfeYZu7xvb8nf4948h5aN/1x2dIuC83ks9soMka24Nd18YdM7+vS/LePgh6GzDIceCCXqqGvmBTChMg1MrT3sgyKlcq7tlvklu/5BuqqI0GS9adn3HHgJjwhdasTtZ7UcafbFFoaVaj9H1vEf67QknXGOC/SicnkO+dfJ7mOFNCrUiI0fZnr5H3gH5t3uHE3OJ0/qmWA6gFlgrGunjRasfUZYwC+y9zDbdjaSv6wkRlJyscKxuLOAGy34ogRKcF+6H0EXLQVoUR+lu6yh05TyuNEXtGDdKOLrr4xphyrTVfWaDZH3oJKBoK5aGHhU7DZsMmYYqYOB214hztfWCrJo0f8pnXMU6invY5o0ouRrrBkov8K+BlyEw8yVOHmFlxB3SRUIuvtf6dpb+A6+LiovLAoEaDHlRoEpIrUdqk0Q9uKTbfkSCsN26oAPHdrZHcXE77QqDRllpa0Sjw1qm6vQtq3e8hitNiepNF86lAChLBJyGcnz2ko0WuT7BzRXoq2uRg67wByg/hxXD9dT4M3SEmhmt19faJgtivZjiXGU3LQCDX3twbF/QuTPfAdTEwlwvUaqr8PJ1z/FGV4KQj6/FPJJBBATqM4i3qCBBGh7bXJ8TojGJOjK8xmJd6GUofqb+8HXrwE+9EV3ZOPbPQJ9swg8vZxoJHCOQ1fOLFi7Vs7ztfA2i+ykMcARDPJiLZDkIdwFyRurJRIRakNo4fHTc6NfgFAlwzFSOF3suNkCWs0awmjJkyNXdEIKq3sT5AsMGNaXRgZIJE3fZoHQ1pVdUyMtV7GJ91MEK4uqg+VRjopYTbPIbbeulq2njZ/TSzzZThUg0B8Q09hxlLBNOi6tctF5UNZSNfmoN0Yi7sbroFlgrdGnHdu4/JjbeMAdaCCY02IKyWRzFyqYMXbjBi9fWCyRt7qDQveoZ/WDL57Dh2z+PkQfxUQ/zWryQS5Gx0l8cZ0sdiUmndtsjDEw6XEkZt4i7pekGltwL6X9H0k3GGT4U+RLi1+6FjJNugZCJwCQXgwOurX7/B1D6JJQFg50Waj2ipwDJcaW+fzLuF+byzfVI2Q5GevA0qrEh1HspID8bPgt9EP+BS/iocPLkJX52wAl951SJd1Ne/oGAFUv5C3HOqtcWQLh/cmApRGtPcw6Wkapwpo8hGwsKDYHBr54tUBroqe6qCg7xenyoYIq0D/S8c8XmIFJ/I3AE5GcRZUsBLSTEIVarvXvyAyJQeBWPRsvE2tTZtMGuxS+20Rqxy232DG7lmgrjLeyY25t+evmDtlS6y2roI+aEoBuGeycqPaoIjDBdd3UnEFNU5U4nkoPbJjMBS9JgEPuLnX7UAKezEb7vUbl1Cj/5TwSXjgGYKpgODs2hA7SvJ1DSuftB29WG6pEqjt4mKHw/cOs1X8PnpEQ6XUIeHSZkM0w8UCWrHJxVFtck/Xcsg3dtk1crzAoVzwO1Grjg731jVNNJrQxk3rV4WdBBfpHCwG7Kk0d4sAyLrxDSOiio6aAnghCvsWRNV0Mz40Fzb/3OzExlNHEwA9YnCZi4nuwbDJiO714okB8QbiRMJRkPCfdU/r0NzytET8xtpI7s5E3Ol8yUrWJj1DNM7gGsxeUG7dD7wGOpA7IYwqWG31525E0y8ZIytZknSLcN35uDHJ8Eym6lqdxRdg/uHLpxUk7SL6Dn+TIe+eii3ubEj90lVL4c2joA5puYslDoTaWrsfEHJ7iyrKGa7g5DHWxkcB995Zk5coL9hSowZASKdWMpQ0HR2Dv/ZnDkO523WXlF0F35vTkIxtjjn48CUXMfzGjmEhKOWACYonLbikFqpvQ/VM0XTPSbmQg7LNw2FUN9itOTb4aOaCb74LC88F++KJ4azDVYVpxXC35bfsqdgK2lngxfFqhMOGEYe73c8l9Ti5gli2PejI6Hm0y90SygCRfiI6fOa2qBoMKOnoLyW4M051d/uz/Q3vRIgo1P0Q+LmgPlLrKjxxWE4Bz8pS3H0OwC4Z93RPMcTCrhAWmxmwSWNNndKUdI+0Cbkfl5NFeccJxVvBNCDiocwbXMMekEFPuotzsvo9lngvUru3K8eFcopeLEGL3jR+UWaJHrk2TrBBkQ0LYWzBJhp+607Jupq/ElEu26yMPKXR6iXUkbPYK8X4grUI47PUy+1LtCHadoazQVT3YrnDkjVausHVJuhSkB8HGf8uvEfustVvOxc7yxkqMj/ThLtVCXKUFbo514Q88t2deE0aslFeC2QXc8dd5MfIrdvDwRXeYAidIUcj4VX5gt2Qcf/54oL6jplPcFRBMhLBc5d0GzkyG+TLqswZywo6duCrgEMf0KJL0FqUoAAsAxpznuCSr2YTMBXza60MnzBFouGOqECR4D2/6+fbtJOUWEuuf3i8zUQqdJVuQHbbOmTX/TWVw14Nbp5gzk3pi6SdGS56VW+/tf30XRCWgIUvvxcIdWWU41PDSyKrTiGhnuMK3H/b4dEm7DaK2lAm82X+Kgodm1uebg4E0ZvcN/xFx28XHAv3hFd0JqpIyLXcLa+ZJMF3cOJqINMgJ/uf1ZZBCHNWbY7AHPm+caqMzXDesYXx1J6lzFEaVuOpTSO2alVO+QxSTNsspNCdV9P4VrdtmCt8uthsLAkDlJuOdxKHzMNcg0X/f+pHKZSCrWEfku9D65SwSVBkTi2pwsK938lkTrSxPJylUfTwMP2x0FSfI2/nVVBJiZlB5mW2JCdW0/gGxtTCfxdIIzg2FvW+mLs0WTZfazUrMbQFFuquta+Gb6Gb+2SPTAaoNXGJPh7K7ZL6VpUTrIhzizjFM0uQXa9r98cf5iVRYwd+rZOA6igLquS9HDW9PTCovyUpCMiaSBVGpaT42g+oRg189L/KBHkjs78sOXhPEq6GW4O9BRotmFpBJgW5MhszrALMyQ0UoXRu6PtzwxBM6fZfcUZiC1EToOB1DBnViKwFtCLUXiZWQqZubJvIniUFR0iltSENPRFEystHmLOyusYIsyFK37PGaY2bC6GuSkAKZ4uC6i+qmPeroh3Q1nygH8FXRZsrURAnxmupwMNuz0woWtbK+y5X5L3hypaAU3Hbhj0hJlJkkpZtplYAhNKuHByrdOn2A/+0Ls1kn++XZJoZfM//Ig0i3PR/d/08dGitolRuULJHrdZvVsGHSIj8XjQZqGKcMlI6C20OrU6wytTx5GuINb/6XglyLCLUAl9vPzIz6xay+tdR9FywQhTDedF/Y7JboQl7/RRSYk35ungaCIDTdh8OwqMJj/uFKrWYFRSJ9GZyU/trS3+R+1mV8M28KGNBv/xe/751MjEaC5bex/tcoO1IiM22vhOdFQe591EVGYw6NwJw2Sfk9nFnZFNGLEVncVbgH+7KE142Ekx/GcXUHq0AxwdfLx/cbRek2T/Vk4Q3vkYOSXmk6FqbuKddTv/z/Z5EF4LMV0OrJvIkepmPTpHX8PP1gEMn2nwsd6azE0ql2KO6nh1SN5UIFvdtJFuh6f2I2NsBkbG6lpQ+y+zUIGjn4KYqeSS5bMvk0rrADmR5HjxI9H6VH8GKWkThx38o3AzcMP08yelp4GZS1tJbiuXfLoOFjBoyFnf+0vOmXmzrbn+xBtIoWmBT1eP1E1tsJGOKLlLv42nMdd6glcxhx/NkK9tInZgYkrlz5q4ENQqbwgYAZe6a1fcKkPWXpqJLDMSlfFtc3f5E0kfYxbDYKY+rH0PZH2RPzrpOu6N7SaXrNoDPFw+iST6e6OeG10Hw4I6QzPPTY4yqFTP5/ec/wXu29bVhVcNgnYPddBo8dh0682XdpSMlLzJQez88fb56smkUlxIVpCBAojB/UlyTVtxEk6IDD91mVPrILdLHX5epz4QXUWx2VUOH2zpV2zZHIZZH+0RVupo13g9hirIzGobxfYTAm+no0p572sxAjUCgPiMC3Zz6Ks+qrWLilGMIhMYrdKk+r3H5PxyN81BPx7vErZwuSfCk3PptawcEvnDaP04XgbZ1udyCG45MUOzqdW0wBxj1MVyP06NU5n6ZBU626RFnO0qsCA3oCiTbTs+QAH3QOQ9sQDGqk8ylCzVpDSrhvctRwJBw2as924DZP8fhCTI1svc/c8+LJqsIfAR6ZdzIBGa/zhBTrDSZm+zlI4zHK0UZDLVW/DM0SXy05cfhtgdWIN2mXrSsDy45pDPwuOi4x5NJVAfLRkKAZCF08BS8uj4PfzX+slOb/sCmMgRt5VKIUdKxkkbTW6fzSwruemdIX+N/CPpkKr8TAg9/BpD4Up5thQWmO35GI3QFwZsz8yzHsqLc+ooQ1p6Uf31Cd03t6K1zk7yEet2EzcnZOOBliw5wZC7pBAVCZ31nKDWBRb3G58C35NZ87AAgQTLFF5XJ+VX4ADPVfrtIbB/YQf5ok76Te6Nybei+MPH3zo/3oG74+Y3J3ShYmigN4TvU9Jqurn9n9MslVyd/nil3pfRv3JElLKYTPe3n8sQl/W+pvwFayXEZSbiyEq0CKC7yQKER4dFkU9AciEMAAI1q6mbgQSc3uZEwaKTQvenTv7Cn1V0BFESuhCAImxmtCiSLtFHDwaoBXweoFp8h3lzMVYUatT34LuZ2Sfzjm62iC5loxdxydV2AdYLeX9tmmln0ineBqUXB5rXYchRxPWvZzGGQDhlX36k+qd9J32F1FAdWxrUUducpzEv8ePpEKXsLhGF++6g0Q2m2yADVX4IVxgol2XfiQiqqTqh8fmALto5VRrTfC9rXIAAJcOYV/xhLD6sBNevLASLGq1Ssq8FBHRdaR8PZ8jZkvleO8gXov9XEaG7Z0CXaiIuG/Y5PhvXFT0pDs+r4PaLi+c+xIhZX3e4sjDnmBzmy8t7eeGGPX6dQhzvTfV4qcQzXqytz10uc+WMX08Mnr2fIwaND97KbqXvX9DlH5DWptdFOMeXq5Fw4dhVd+VAWYi7N0g/4/0PI0KmYoupNbsL3jTUB7+hF3fkY5/8o09HBxJ+Y45hfElxpluO86Uwi4fQivFeKvSGIzLlALjjcuCkljFC+VbY/NRv00Z0Mv+GakDsOHedBez5WlNC2f3CpzHfU5avFpNBQsyPBnJPaUfLrMje9P3qhyNsoMNBptOPSauBK2zw5mvw97BV1+4UlgAaORB3lLW6O2VYkVTh1U3WvTmJcUwkOn5jJaKSrlDKd48XR+il5vmmYrn5pdrjMTNTYMrQKCBAGrOzlqTuuGDE71DFHOlBZegUiRDOejyv1rKwePFzqSXjsbmYz86HKu3IF1F45stD3yqRudxHwXUl5rIr67I6TRnrx0u+BlD2+wb3A/sIqgqGEVm2EM/MtGCQ+KlWxzhi/jTKnVXE+V3Yb3+ub3qEGnXmj0B/zvVmEYiw16mGYgq9gXw9bJirxOzmP2X5Dd1uDWd1oJcKjmzr4aEgTT6qQ5bd25Ry/TxxB3bU1moqHdM84naQ4M48q7z94kOh/5Zemxz3a5a3Sv8d3rBLnJY/QuWFzXnBBEOxYNlryJ03VKhvRYFqHKTiEZYUz74AHBisnwoJa3qZ917dis5C3ld9TUaEZjsVeIMZhOFBe++47d8P98O8fLhWZeMz2Ti9E2x/c7OfPPv3kTI7Aw6mPHAwmMGf1PgtQziz9Whw/9IPSHsdnvqO4SUI747u3jZpola/fhKMlDiIjNc2o0nYQNSNOvQZTqq9kjei3gLM/AwFD/jLaE96RZJxg0RhyAeNS5bd39DyYJyNAGwZe6HqnAZQMtXoditaYp03OOf/zwskxI2hWvkqGwQzKIhlkb2uZBJMYBfvo4juVEL1BoZWKXfngUCkCCLeXH7hIdnjC+yHBU2pGfkZS2Zka5VJNXwx+0wG4uZFOd1t1ftYfvHh1nR3ej7ZHjtAZb5ZWrqEuyYW5y/0GfALD8tJ5zTDzQNQiXQmFv4lNr3KAXJGkLmlvD3c1YjZ2ySaLmzGijr3lqpfK4nZxeV+K4KapskbI0qI5E+SusD4trwO0Q1gopVMQt0IuWs0F4mZf7xg5Ly24Nb4P1Kqy8mG8fwaYsB6CPvr8WYRWqjypmTTyKuou5wlSOUq2QRyVQoBiEGwzUSPHduCDhxVGsZZJUokE0fSfRKsHDMpDVfMcnbzyUVkeBRp9q770sP1UgWhP0Ym6abxDHA1q/MuUINeJbyINpZWkaK80kPVuDMSifMgWnp9Hu+7HsJEseNtNrPGWzSmclAL7bQhkdcjNKRustrL1/xSDNW1/QGG3J7OIX95UmwCNLweHK1PnJvry1bvrgHRqLRj4bs4wepeLZ5SsaoKpaX1O0M/47g9xvHMKvUSa81F2DbQKSMgQieFozYAKlmbKlQe95h19xTWVJl3mpT50rfTef1KyORxWxWgwtueCsEXGnfkyoHiLQA+toUmjuxbV1zjRDOc5Pgy4W9HfBKV3A3i65nVt2RIA00dtiVon1+JpYxTGxMb/PtzR1Q8yB9huLYDMToKCM8XC+lWd9JSG9AuA8vupJsgYat15K0/1/eeToSlLQZuE4qD7Poq5Pq810U9A8K3/8fuWpPVpSHo6+r6xahrjs9+exhl7Px87CHrs95cLS9RzCqLnRQ7KDqow+FrrHXkjpKDPrgoycNh2cCA2/HcV5MGBWnA4J6tNrjb74V3gJcvqd/QhdxM3xmS4AQ","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file From 2afc0e94a7fc480e44d268fdbb0ef6d21075da3b Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 05:03:54 +1000 Subject: [PATCH 68/95] ci: pin immutable companion database matrix --- .github/workflows/cross-repository-integration.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml index b33bd36..7d1227d 100644 --- a/.github/workflows/cross-repository-integration.yml +++ b/.github/workflows/cross-repository-integration.yml @@ -35,7 +35,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: bf9ccf8a2437a319aa7dbf6499652a744f79d8aa + ref: 78e76934f3f4d8f9688b72e8873565f819d6a374 path: paymenter - name: Set up PHP @@ -96,7 +96,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: bf9ccf8a2437a319aa7dbf6499652a744f79d8aa + ref: 78e76934f3f4d8f9688b72e8873565f819d6a374 path: paymenter - name: Set up PHP @@ -200,7 +200,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: bf9ccf8a2437a319aa7dbf6499652a744f79d8aa + ref: 78e76934f3f4d8f9688b72e8873565f819d6a374 path: paymenter - name: Set up PHP From ae365168d33362bfbb1f3f0205bc995fe307a011 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 05:04:51 +1000 Subject: [PATCH 69/95] docs: repin final Qoder checkpoint --- .../en/content/API Reference/API Reference.md | 24 ++++++------- .../Architecture Overview.md | 34 +++++++++---------- .../en/content/Core Services/Core Services.md | 2 +- .qoder/repowiki/en/content/Deployment.md | 2 +- .qoder/repowiki/en/content/Event System.md | 2 +- .qoder/repowiki/en/content/Testing.md | 18 +++++----- .../repowiki/en/meta/repowiki-metadata.json | 2 +- 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index 7eb3ccc..0ddc0d5 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -23,12 +23,12 @@ There are no standalone customer availability, pricing, reservation-create, reservation-confirm, or reservation-extend endpoints. Customer quote failures are generic; upstream bodies and internal exception messages are never returned. -[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php) +[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php) **Referenced Files in This Document** -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php) - [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) - [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) - [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) @@ -82,10 +82,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -124,7 +124,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L17-L22) - [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) - [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) @@ -141,7 +141,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L17-L40) - [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) - [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) @@ -151,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L17-L40) ### Endpoints @@ -190,7 +190,7 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L17-L40) - [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing @@ -229,7 +229,7 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L17-L22) - [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) @@ -313,7 +313,7 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L24-L30) - [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) - [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) @@ -343,7 +343,7 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L32-L40) - [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) @@ -378,7 +378,7 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L32-L40) - [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index 53c0577..d954bb8 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,17 +2,17 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/DynamicPterodactyl.php) -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/routes/api.php) -- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Services/PterodactylInventoryService.php) -- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Services/ResourceCalculationService.php) -- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Services/ResourceQuoteService.php) -- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Services/ReservationService.php) -- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Services/UpgradeReservationService.php) -- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Services/WebhookEndpointPolicy.php) -- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Models/NodeCapacityPolicy.php) -- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Listeners/CartItemCreatedListener.php) -- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/Listeners/CartItemDeletedListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Services/UpgradeReservationService.php) +- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Services/WebhookEndpointPolicy.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Listeners/CartItemDeletedListener.php) ## Reconciled Architecture @@ -136,9 +136,9 @@ in Paymenter core. For implementation-level detail, use these versioned repository guides: -- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/02-SERVICES.md) -- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/03-API.md) -- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/04-EVENTS.md) -- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/09-IMPLEMENTATION.md) -- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/DECISIONS.md) -- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/PROGRESS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index e484661..df56bc8 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -17,7 +17,7 @@ `SchedulerHealthService`, and the audit/configuration services provide the supporting policies and operator visibility. -[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/02-SERVICES.md) +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/02-SERVICES.md) diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index 8323c5c..e9d1190 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -27,7 +27,7 @@ by the cross-repository workflow. Before enabling dynamic stock: The API key migration encrypts the stored credential. Customer errors remain generic; detailed upstream failures belong only in protected logs. -[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/09-IMPLEMENTATION.md) +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/09-IMPLEMENTATION.md) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index a6a7172..db1ed8f 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -15,7 +15,7 @@ companion lifecycle. The reconciled extension does not register cleanup, reconciliation, capacity alerts, and scheduler-lag checks are registered from `DynamicPterodactyl::boot()`. -[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/04-EVENTS.md) +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/04-EVENTS.md) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 8857737..ef49313 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -14,14 +14,14 @@ process-private named-memory database and rejects inherited generated URIs in child processes. MySQL/MariaDB tests may use only the explicitly named `paymenter_test` database while `APP_ENV=testing`. -[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php) and -[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/TestDatabaseGuard.php) +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/TestDatabaseGuard.php) **Referenced Files in This Document** - [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) -- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php) - [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) - [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) - [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) @@ -86,7 +86,7 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) - [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) @@ -97,7 +97,7 @@ U --> AC **Section sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) @@ -142,7 +142,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -361,7 +361,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) @@ -383,7 +383,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -425,7 +425,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 23e3783..dc76c1d 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"5ff9fd9328ed4fa6c167c2b2f2dc5296c0d87fb2","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted:qkTEybd9tQzuDstX5IzR1CXs/trJv2Qp8kaORmGdEsjOxLytJAqUuHjP06XJn9y+iXOi9CHh5MccEBo3czEUCbEI3xi3jI2FX0U5Hb1shR6LDZa4SKyGHNVixTBNySA00Nc7Lz+raBGyJ9EnF9lGDKWB1J0M+K73LX1rF7N3R69cErBcAhuvCBd69rsyUTTKSXgEpXu6a6WBUCYLToWdn12p9VWVvjTtcSe6lRUrzgs90/zIfQVq9RYyW/9LbF/T1JjqYM0NGvS+uZhPFi3p2U9QVLIuGWoSFWeMUW7i/mctoN1NLGsU3TIOSauX990uB8YSEC+j3CLEU0RFn/c5OsWoAXtfngYrjb4AGHl2NEDSkwlciQRkxkMYxFEZyYcHT8Gpy9mvFvx8bbUg0Pz6UsIgth+Wt8ksCwhqUfDKRSDFIXTTfvORPKTzfkyLwlHIqFcgDPVkG6zJI8I05IjUlXG5jKJQFuSvTIn3yJqmp7ZhvKQoeYLzB31v5M+ZOkDLxB20IFzyEJJaajhK2ne42xddTRga+uACLExPlaXQ2RJgP7aEh4BxFflfEZTJ34EAFDODWNpg+cS/h15EWTsUaCG4uC1kiMBrOd2ozslPb/B4Edh29LEeX6942jquAGPtDbui9o80AA5R7YrXIWL0yCvKlGIvVQkiQRQKUdaVYNvT3BlqJ9Ka2WMvnXeD93o7uFgQDqkb92et5LlCLAyZL2hhn/HVQ2au4V4WnXgjVYGwqLpihYFplV2o6Ul5PDnwJGD69mAO7aSGG4TBaz1vo7thcxfYaEN8buhL/QRsNVzwqTeN25dxKdYd+zBxU36BMRYfjftV5aUHpmuuyJJkM5VRKQ6BjVw6woeWtQG8FgIoVUuFHpxorMTccI2C1mpkmzgRNMXQ85uoPlKkLHfbtEhYmKBBI5pISQM9VE6ya4qmYS3ZcA4Gby+GuS+2myO7b+pIgX6Gq8Edw5WSPn2Ei//99pnHyVX5UPawG98jbNRlrQs2TtcrBTUT98D4BYcMA+ktxGDZix3F4RcLx5/elIhe124f8f7S+X8phIq7uGTw+ZxP8gQsdLdGaOoF3tin+ZOK0iHk3oIa+E7zaPMUeNmQcixZRtKa4oIeo6dr4zHVltAOiLtV52OQDsPPCU8HwUO9GFXeTYlUMXhErji/Bg7K2iw712B/4pQW0+0M4atRKpXUCf0AstnGoCz8LlV+hEsMY8AS+k7jCk4TW4pv758c4geH+8hGXMLUSEdVybYs2P4Vk4c8nAaIEP6jWukiDhIps/dyb8RExWg5BKcfGJZXTWi3TBQKnGIqc1JgXXJUAOfGwP87PHb9WxxWsvl+13KF6/JUV2RuX8NWSAmST2z9I5whzQnfem7CCc2i5yO6yqpJbPOt+hpYlqFYp/yd6gkodn84E4+o9G2F9NamhIk1rCcqX0YoYhYX3he3rU49QIUaNev/DsEKQc3s+K3yH3L969uk8nvcFIDEREP3Ke/07RicsySihmrgxJ98Ld4lr2V25uD69/exLybGUdn2dDcVBUfI6jWrwipyYCInTV+f2WDOy/ki/Kv/G4WbDZhIXn006l1s0GcFML1GXUTxXmJY0ku4dOxbpkSooJ7fw4n3y6hHWfG8HpJT6bxgFd00CbYoe/b0gzXvAaWW8vpkN1sYSWr1kqeYKUzdSIW57T/K/LOKTHdgZA+L0R1R8CEvL/ecL3GkHaFg+gEYwMpDWhf5rCtDxKebVIATR9aw07hbWczXdZwkDXJlVd5V5vdgORzxjfzO/OFC44ruOlxQSlTZLyulYQFp9dHxHnHSP0L24zQXaZKtefy8cnmOapkooReZ+wZRWiAb7fxmo9D1teGxlOU66NKDFzhuXbd+HpEiPqGRF9y08wPLPou9goHOa/JMQmjgWBUVuQuDbR+a74MSWaZCcIwojBJ/uBzCR1IFP2H+BJDuKSrdeLDMuW5EJu5KRZ0B7R+zFnwOxiZ9EYJTIFO4DXNRb9ZL4JZaZJDqwUUgBM8pWHec/4cM+iRi7hh+rkEMQRAMyGpem2L+oSpr2mWWzpe8wQhlaZeVV2sbybXQ/c1TEtK34eA4FlFqimXo12UKrmimZi1mkAyuF98LXH1wCLNXeJVLWZOMKrSl17JGy+Rgsx9dEnAmdAOt/ePsBXXphzaiSY+6GMqmtIINfcgpsvFLf7VhdP0yeZ+kkaT7kJ6yYu+EvJqw32jYBjw3cBy03f0wLMX/dMHo6VPVsef8AiKqBBoTxb2uWBbY31nXY9EQgRoYajhQYdmKkqEJWTkgXQTwQDHnUdrR69KAqK1wYfDX38GDERT9ibC6fXsUZGq+QgGm8VZHTsFTnVWZUi9EUCA1oH4p8NtjCRKQE1dUmCiF/sMRKwCgiHZ+WmKV4ixhHV51T5RAHQ1fkcqc+hPFcd9uEqHPrwvlORQ9jh5rDbFRNCijsw17TiHm3NlZIZ6TOhCPiPO7135f1/4QfMvhj8NftvFreT17bU7G6ZhUQAvh6EcXhWZ2LDqZR6Buji6hu1u+6WgCFFNo+TSLl+h0xhKxqKlA0H4FQImLcJdXn4MBTrmQhqMe5H1iyxIN8bhT42s42eS/2IJqrvjiLVVNiU9DbRlYBe5TsLfZuC9GQsWYHdHB2KAAAceRlYBlwnnnVPexQl67P/G9sMfPJkJP7aduEQc+ikG8og1weDdx5GYauM8O/D1cxi8/7lTsEtDIGXuCC5OOHBs7utoXRrzgtS/D2kgNytqDqSaHVKaNy8NDlNMYbjHbsr4ffxNCRN6Pv2NPi1RODmwAvliw6D7KLOfoqACJKyBasvMnWyR24InlREQefIeRrWJ37pr9Vq55Q3FhvhZAc8rPO+f3plstLlPFQuqz9RWznCe1tPE0niOz5NHBZI9lhIv8cOJgZRzQJnMNAIPVderB7zfqLtTAiq8aipiVreV2y2vrLz0b9lyC8yWPsQK3aseiv9yw6i9ehl4z/sHroeApfLHdyEscUVNJXOvapP2qTfZ9jk4hocuqydv/duI2D65jyGlk6QuIPkjjMcJ8zaFur7eFq177IRSKIy0XT5XPXjUFSsnXp0ChOnfbgKyNvD71SvzQT7GwZI6hAH67jxNZKymIWPsLwAFOl+M5XOs8X9EnYbxKTReoFUvgerc0IprGMeJ16tH14Yd0i/HHak13ShbBkqSOrBhhWBRCCGt73qsgdMPKqQaZAihM6hzVtV0uacQePDcxX005Zjorr5rGsmt6BTBWli/TnwDZB3Ttch1RUd2LJTCCIf05zCDZAtrx3zbm5Zoti5VWjScQta3sIvXlpHyQkCjB2varsGqAsAM6xbX6bHqsYlZCwlk1uP/VKVdUU65hWydtK0mJCHJsMV/H8ph35q74Pd6y7yvcwg6oKZCuQCA+Cd9TiyAc3Nt+wXdMFlMxobEz1J0fL8o1BKpsKI1yNn3xff0/UITO4WG/FJ3ryJ1ROrErGmcxjYSgvBsYrkhIUJRMx67aSnqHC3oQ7SWeFeJrTuyyrHD99crFg1wWW/Ny7Jkko38NzNnHHArluH3t678lUA+iwYkFUmGoEtS4GEav6aW5hU2cvXiL3Sgog1Eht3LcHBLRR5Bf6n1QOINMP3Japm34G7BaoZ5TNwpgoVoJL4/vUu1ncx7WYfgP8KlUhUAWtI6NFt/vMxjZ9vhCM4Pgn6dQLn/vpc6aYRsyEZChXu0wLqM9O9zLbAQ8qEOA0e42gpKoXjDUYBnNFu0Z5xjiaRu4B0LT64hpm/n8NvjzD3dL/9wv6xCTKdt6T7PmeIUrpxi1OcprTww1m+Op0qyeOzKRfWHQl9S3dREaZ4AXqDFETvCYFD/VJ3U5pXRr93uIH89E9eoGaZQbr31j5m5aYERY2ZXF99fhxPSyd4rranhUy7m67NgGGaNgdqnH/9rR1NPpFb1xUwymj4NoSg+innBL7DfFKsWMHumXC3b+C5jvg3WudMgI0+ODGO6MoYDiERrxIidOP5q8ZN4Jfts8pGffE5/sd8zNMP36qD4t8nF/pskZsgdOVcsUzPmuB86IFlV9bD4eC/RdmJS/lHgmgQ4eTpFRNADPwqz9vkoPtQurxMYLqnrF7LElAIGXC0U6k/oyDz7SKDz27N5B7ryjSs0IVLV2Gy7ZncOKbEyj9CPNXy9vR8rAIDrFLa1QNw+FwYgPu+RoyTDJ9S55NDjpALze3Si28hXfGIoA0HSvM4+r1S8EfRrQmWs1o+qBh1pDKt9hnFpqLjq08Kz/UarsuU/dKAxkzP6FSPHWRYY3YCd6U4lJq9LL12d9FcrgYIz72opWVgWq5BNezdmM5foqsAFgDujPmGbB6YdL7kTyt0rcxMBkjlP56SnD8hLaBG7oTkf4GCzquMcMhaFf1pklIKJi90kufl9CDN0eYHjnF+AzeLf1p/Ruq0IehmliQXA1No4mXjiA2qU1BnmzqTNCyAWN32S+fAkeEfSd+AdD4sMJSSLUhNwaoTQr3qSp9Q0qW2KZGchDCBDXE4mTCyxPNDnHCSvmq+ayDviJacujoKbZNnuuZjgJ5eitj0nuD0S7jD/URAoUq8UAEzo1qq5eziSUw6z38U0v97ZaU0hohyYSgjBAv+umzJOrnY+Wu7SVW/53kYb8GpMhwkgdvQRKZcBEUuR8o2LmYWilmZpKyH08poYLj41wtsUQaVqhgItvECi6G1V1MRg9BzvvHSGxU3jglpZUgzv4dhYrUxabLiVdFRLyAtZ+nx5YSidIxtStPEnWKIR27k0BIsYLP0yO7npcBkx9v7urwM1oh8q6o9mtPT140KgBqUPMRKujN1Qiw0kQ1BM6TddIsUWMS4Jr6oH//jZqDqOM1BgFjEzXhdWWTnwHe8Y1x35EGBfYupFepa8/H/6iB8HUnbLcEg0sS1Hla0OHtaut4N6i/rJNlfBAYjK1tyDv/cwm/bEClj0JzLRWKjf1Ae/1b0LYWIDReal8V5YqrdkB766d1yx+xZ+oU0c2wAn4ij+Do6RRtrV4lTFGs/PNS9CpiYS9yt6xXt+2rFuKuWrDxwLl5krZDJKTvpO0s9aF7jjljsDfcaKJQQTlTkL0h1z/KZxm41bg+KcbsyptkUR/8Xti/fBFOUSBOUd2E0ppEA8/r2pxLlIYaIQb4dYsI3bqvONiFviW9qExQQZ2RYJ9dLDykZiujhQ2nEJQOaCc7e+NViygsPHE0NTb24LIPbnAQX1W1PCt8RtndICZAJI60dVMni+ctjifd/hwY0Llgl7d866veLh6q/YZn2f2qBr6ms+ar6mIrT0zapYhNG+hLWaXxThodnNG02y4Ifd9wFSEkMOqaeMXxCBRquJ8QoH9wSd6nYO3VDChhkPpqdATuWj5/hI5SUtcmDOKTe9FtpP+sSIII8thsMraMi34XovbHYPFdAwrSy7P46GbtrZKTG4gKr3ZtlGIMFlYEPeTPL322mNwjrj92Xtiv99blZVyVShhhNHlHvcFPjXvVWiI3iNMcdDs6Q4ZRSjkLTxVaZcFHL7S6/fj/TeKcISQMVvW/+80GI7791wFpgzGt2UfMHcCakrxgxpldcwlqSTVsMDRMkWaQQzsqaODqL9IZoMYyGJweawPyIFbCanAUfBpoJJUHrPCPVTzsG+5TupSkaxAqSmonKiCcqUA4Ra7rc7B6H67hFyaqzDcQ0HnObKpJp9Z47+70k1bqqE5DzVn9jE/pXNBplDGe2EN1ElmWGZ7ZFl5RSZeNxhCZ90+qOFe0RfYZyk0g7qi0KDnSmIttTqBNXzyktDJhs8cqPvs17y38gAjI9Q2RtR4ShU++7m/id9sSjv3xAHhawuUdS9Pgj+OO554Xezol7Wdn0kx+oTnVEZsOUDtV+8dx9M1X+b3yhEONQZQnpkLzz5trviuVmzgLKxgopFB/Hmh1d+E4KOHkV/SLfy+a1bz2FXqUzu9fX+oRKLKmJJD5Y4sp+/gJSH68oriVKGq+hvF4F/RBmkKMXwE8KTw1LUFl7dMvkMuAKoNnklEyyyVdKit0vtj00CqZhG660jA+5z41hadJqUZ+lK+ITqJjvUrjmKOzQ0q/CIIJETrpCfkjXZmqb4Ebz47DJ16umz/a0IWN/tiFyuwoxzvdGEMGKQ7o8Pd8BciB3LBnFUoHMtR0yW0jxctOzrftPZ/vh0JSHOp6ux72Vh9AZgi5TphCRvcpKlba/I0IyYzkevNboCRgYQP+Ap5rj+93nXiGWTfRk2mSpyLral3GHzhAMgl972OIpcT5/Jm3DX9Rt5xScquys2wJ2dVY8lhiPPr8zMvy0frQL7I5056M0eQjoInwws4fIZtBfEYy+ycrVnZDK6EIc1FdGItERZL7gIhphZ4dcYXtj8cRF6l2PlQ504mB2w/WVH6zE9naxlibeNF1JpvRZ5pKl2Jna35M+axy4dgC7rhji2OIE6pjCle8ZW5yezeopFZ+gelvlQrNqVR8pA6lGoPp/VixuWxbDG0MqAYPN+4+UqdXGvEF5VGcjWCJwfE31XaLZNL1XKfqzBuEAD6R6SuRb4ik9jhKDmCOvYyF2y2jxovEJKGv2qQ04poITEbD9Z/VoGI6qH+Ldfx/pHSxxYj8QfadppQBhfWROJ4HaW65WXESK7kQnLKzIcRk97zLXiBUAfDnoROqbd+VzlfnXGEogSfskcNcyn40WdRAZ9EkO3qWeT8L7eGa70tx0EDmSfkv4EUZhKMKbJwsAyedmc/tmVQyk2CVQCzgBMW5AdHgfkaHRTqiPuRpkSnVVCfi5yUcfdgKeU5eho1iFzrBJ5FWc4LtiU88uOOFewUSqski12Z7xAZDF9QH4eDOcWEIRwy8nzflI0C18Hjz/AVBfeKxfuVf56MJD1M9b5ZyKgXF2uv+2rtOC87aqaGDKkmG36eWMjUpj55xm0OrxhnFYb4io1c7Ar9GHOTCp5d9T8b8AlmDghYu9Q4BS9eu1fC5mk2qntj0gbtITw9yrm94mnFR3epFBM5VimXsIKyfkN6vaxi/VYxLzs/m8P2/iMz5YhDPSpEoE6dtGi+RYFQoGfmf4Kp51MvhxKpBWzIKUZ4oVo3bSR/xTtA8g7m2Cu9TmGyGzoRsGZVWPwenitAOr8BK1F2gZIetevGghmmjb+dsTllfsZSkAVO+a/QWVxiylobFRc/EGg1uQzlL5YM9+6L/vwXg6zBN9kGoGj7BzOCNk1aNyPkub8+YZrb16Nj9GZcHqGJWRlAqG/XekCaEDdi/tUuwHPCTvJpmceD04ErapLgvVI42e6zgSXMnb4xQ8znJCFT/H85Air3ZAMw36GLTdxZbw+csNjB7990zjLDB1/gslSZrLuBFvtO2ciWE7AqYJd4YUlhLF4iLpy5W4Sw50GjAW444Fgp6oVJnQlL0tV8APr2xbLWp9Eo40IOgvMNVPwLP/v39jsXjKT+VrFgPBaEYyxNIKtx8MAUPhCaPKzpEL58BAo4j14o00Ma4zDTGbFWPXFfbTMBZtDjBD7n6z/GJZUFz61giQOlLsQ0APQW//bMxmh8FgqEujhae7IEDDgm98plwNfmKQKAv+nZB6h9iie1nTVLTm5P4ZSw+v3VpETskl9Bq8RT65DPNdkO8pqMBj8J6Xm51FlrR0ErRv/ynI11twA390S1F5cLg+OLAOx271Of6n2wxWTJG/peXEcAVfFaXXlsmvARiKku8WQu3W/38Uulrk1fg3setfivWSWv2nJvb6NLQyqX1aN5B4vMtm3Sx4oi+QCmHpKr4+n92EdLsHfZJa4Ldm49Lqk6CkD6kncpzbtAjIRTVUXcC/P5ujAwgZPyCyhiwkRJnc1ZBJmbF8JianRsBqhnzXpUBlsOObVOdyjLn3rFDaigXy90uf3vyrSJP1LBqN6DjEKFm3qQXpgmEIqfjLN1upGeb3/PrJV6ylEFwbsPv03ZZvlHP6RLo2fOotcZBh/E+EVPvXv5bzjYVWfDbV3wf6qnr5ZX0muxzBkYOnVp2m0mDA5cgkhI8pY8vXhQvMRBPQpqe3OPJmr1HySivFsIWnHbpSKfTYY9BJYLlEP7cQWwboEHAeXdMpmTx1IOUnJAO59nOml+xyOCSwelJo2W/nCTPuEEGkBHLjpogzvEBe7DZ8j4CjYynzKdd8UEVuXCkKvQhDC6HGQhd56b1uxmxh+Aq/w07/nYu1Y60vEk0Mbi2s0Jo5PpcOcG3ZmRXGJf+1csDOpm4wCi+iF84wBewgxdIegpjPTRopBHEPYH1MSRHiBliqdxf9gipweLAX6yLOk/N7H/gqXarYkCdZXxEjpoZauMfawkM7Q/wSjTKV/vi0en76dmnTHOQzAUjGfBEdm3DtJRZd9XNP27syr6nu2mefGeB+q9sHnNOIMkn8+ZBd5aQdVZT/HvT52vWseAb7488OnqKWAXinkPMoOpx151M5Dwh4n5aMVSqD8+cwTnrSlcuBO+tFrxdDhpCjOY4HRq3Bipo8A88g5OJPBxTCX4Ms9FSH21e/YFA14rMyjYfBMSz3rCdSYp1Ni/U4JT4mU5wGxE0/4djSDcJVd69oE4XKftnVrZQuxz1xKObEy3VSf0/4VN+GtRu9PClRTv63n1vWX4R52q3ibpWD1gSnCxUnMGcovNWSM3+syP8G5yZFHgH8sVuthC1LvODHAa1r1w1gzLAWMMQlYzXo0CRruV6bNDGlcp6KZkgbmOZDX1DWXkrz0r1sTmjTSM13SBuBW4EaNJFyvoV5LLW/yNcUDzhhwysPeGF5df01d+svZEAgHYA8Ogf2b0U7Twj3zx8IqyFfuk+q8TA4trDvU5z/fDNnZazo5r526djNB9+vNMRuxziw0qf7cZuJVMHR5+ek9t5JprtGyXisj7a0LNadiSdFxx5hyMW1SStaM64Aj5w9+m1wGu8Mx5eZ4YX6tXpnc6II3+8SQY20Ui9W8niZVOpr4ybqsaaHVGW9Qzxm6UJwSjtgOcWVb6RsO3i6ymooRxQbpZv39tLrxc42g4Vn8hb6x1i3ukKrvtMUvidfbdR15kWYyV1O5PcPXZ3UnMI5fJS8NhsFLE60UNzIga7p36e4W3b+hKghoKnk6JfRtSn7W2dtJgD+pJPhKOxuOLv+fLBT5FwIOHtDzSrdfQrIeiw1FAOmemg6VLbIGiZY86LzBOGzget0EKnLBmMEZip7FK9xIPno1ek3h+EQhg+aDtm//h/VR8Zaz5H2ls6UThDjbVVBw6ffW3Nl71KdgGDk+/D1pvVIc6yfpAgfqt2IYSIjiwJAlvqWZWxR/DkZQUfO0Tjx7fbWp7dssuOrIwo3KQALWFLOBCEljuas4Sw15z2kEQgwquReMhCByUT8vADZMeN1VzAt6X73/ZByCwoVx5rxFjuZkfpXOoxeSCBJtTBCbDlmKHAEb35Fo1yDcQDSk5TlcgrFG12VRpLkHOlZ+fCRn/T49V+TRF0MPlTh2yuJaAl0K93cs1uqqRATX0KsF7XdQOU9FMx8gr7YrImpvgUCheB5XJR1viAxxKCQpaAPpG8SyM1eAbTsNmWsDXz0o9b1h+iz0Pndozebu4NtJLqSXpXCVSsfLlbAaCdHvQ/hb7BEGKf63aL27oNfROm8x35ul6mLX3JWheWr1oPh/KwLgJhOlMPUEDTDMzSp9XpJksZuB4ricLei7rRIn5YE/NWaiswBb5oknS4hicl8YYYRzryUqOdC/7z3GTLXpmFP9eSolf8/Rzt5KNtJQWQK8SoiAbu4e4/ScgM1wzUaNnMNQ0RV4wFAwZ4vvkFNDzVAwpJqWIPaA/MF2cGJOfxA11Ssuxd/2gHXF65fJ1y1sOi10yNWjdnZjjnf8KEdd8ApKjNpMzD2WayEQXzmXXKQ5Ym9FlJb1oIsSJt9Fv2YauH0FlsSO0IWOu7iMPJ/Z0mo5ka31AtBJh9c1gtUxm2xo3t1qhMGnopFozQqeZgiSufSQ3pgrGrUqjwzCsmRZ4qtSOaCu1eDSgR2+DTJ3kSjU9IkiII0G0vFvR0bwL7nOFWBHzs8LT6eQic/CCMCJXuxvvwTknfgrDYIj29BMK5Q/PoMO7JMlG4mfMQ/65QkdmKvVVdmJYl8d6kHjawEtS0JsTwaPFhwNQcXXR4QBFtfZq7hZTyAl0VJ641n3FdiK8YjUJRhRVErBbY8vpSW8Cw5DXTo6rVtbmDM3GHhGWL/EQmL4yVLnmqJloHiCH9lgCZ2spd6WdTbg/G8lS81eFiE3AdnUvL8nOxCVE1cm886d2z5rJL7xXOBfhXiU535UD1FTXOt9IJAGFOrz3q7a7QBcN0mXqjabPSLUzao7SLxzzQ3N5BBtY9E5A6F/JOeJ8k1azGBsbBmHX3gX009gjdyh2FEi4isGWUYmq/ppVDOKRM9TrYBIusyuL1uJnvliLE41KvUnj9cVSGu6Y+LhOShU0oIZzNqlLz1drq9WtJ0pNOBHHcDBUZIHKWkvQu2Kj08LAVuKoqCUTB+bbFSubHE8+P+LqHhU1Efi+bofZdd8IImHxlzSay2TwOJmYr/vg1ttPsxY6QK2cUYrisuDe9flpa6aZ1TDUghwOD3SrGayV0EtJznsqVdhFFrMhyJVUZNqnu/Dacu5QExvHCzFWycNKt5DhsDafNS4OhLlgZofPhh0ORCnb31pkhnfZH2ViomqngfDk3HZYuwW4eKaQuzAskCW9lIk+PGnnNa4MgKye2sy+Bth5Eyn2Y0CHD3wtChNaro+GGoZpaiOyv5qbJLbMO1FfBeD7EGb4VXFQF4VBxnnGV1OFZwDKoa7w7L//On/9Nq4eFY8IJABXL/JWxphpALlAImWxSgoAg837PbDY9dbowRSrVQjhJZUM09BEL2FR+P3kwPwmzE3ReioFgvcAZtTcjzFZs2UHJSk6Mcphkd6ZCr5HIcqgC6GXPa4Aqesw89Uxz9DZfpR7PJkygyZQzn+nGFe9UDOfyqfNF4MxitwhtdniTtmpFTc2JmTNNGNe7IOzYE9kwB52RtLgi79orjTDW5DZ5TnJIqM3sbis0VBgUGXb5JY7oVpXPDmp5XByCkb2voab6P4uFhT8C7FmtsJVQyPRlddFGilUPX+V+n+ANkBMUhuMdowRyKwSxfaNsDVSgdTuGpOw0N2qr8kDOM3NDaCSUXNLoaxxW0NPdO7C7gFI4vcdYhiHy5lLmxuJD62giIjMqQOxH5cefdO8+eiMemWEBA8NQ83eQD+SCHuzLgo7LoIvZmzskylMbYFIwEIzAcy99HjGicmpxKzHFHyN+CRurnuNxaaMqx6/iNmvXjrftA21yI9Yq9T3Yip/33ksWdy3c7IGe+PI0WYExvJ9c/lBmMd6SGu8mKYF/pMxVOATbR5+xtU9EPvTKfOM7TmG9K0faNj7RxdZdua6eui6PekC3iqcWyGt3EGe5j/do2IYobTVDKKhnMZnSgEOmx1rTBo2KKbY4mYB+RtNvMhRJW4StmcRz8tPcGwZbrgTCjL+D6d5oxRiiZo29zSKfQ/yxmLwBPZi4v6LgZGpCMGcUqSSH96k7eBtSoifW31yPc40wPMNsgRBozhjEagoHnrFGA8uxx1turvhD+04CaMdCQGjZ6icqM9PZrL+N0vjxFN7feMPCHySBixzE/k0gwDf7hpMwZnkWoBwF16bK8pNYxmME9DrFDMG1ZVELOxH1PqMzOqDTB0uv/9si0Y/5PfxIk1H0BbpxVOacW9gDfuwaxVnRYlTl6JDYgDqDuXSAokO8ldVhABFE5RQdKb1J4nx2I7VDmS811kQTLZlZZ6jdvLDKKVq/yvnk4j2rXW6cC1j8cJ140GxQXkK1EYNUV80o8Zix7dY7gJMoKBsCA9hXFD9nexFfhUNHwcjYNhR20syWFFJehOjNJIcRPibYc15Zz5AqnBLYgnqo78xogpUJYMsClJ4ZMBWfGSuoWWio9OqVU3LHKfcvBEU6TD3xWTr225Cw6UVNB8c2OqwIA7Q6a+t/mvH1EKysRXxsk8iOTZ6b0PM66iEtEt9tDBAPzCWrAY4c0tCHRFXyq1UuK7lRWVaEnrNlpoFW08Q3zpt1nUR/chEBfQNOITrI8/imqT+CMvM+0hhtK6aokFYHxdOXeFRDOoGeH0/qfVCAnxv/XLz3ZS1+qeivmj6QmjR+3sKYPAMRv9H+YzvZ+ujz2VW59RyMTJaZswXzBmdwYfL8dSxo7tgxp1B0kJiKMfPaTWty3zszKcCc72NXo+hhErdqfA03QPD/w0kYChY+rX321xwuVFltMhDKwG/b4N9mDi5be+8lpEMlQsguMMFUPwJRtiHK+COc2fvo9hujDwtxhvv9KHE3rouXBsqhqVzezXbnSCJRRQg++FNw0pApZIaiBJsa/oIG5PtnyPFCNSfIo9ua1/gp2lt+Y5ipU8AXJTf2RbmbykJqlGUUo45aqA3kHtH++PNVDlbJAwX29qRziiS1OtvUQw4ld30U5+phiaaVP/Zq9GOs0KT0bernuZcmtau2dv27jESU3l4ipL6yaBpqzRfwWluAJhVizirM9O6Ao87LEahalzvTjnml95d+SCjmf0G7HMSGPY3KMiZUoyeOZ94XSMYssRKNnkx3mzxJjPuH7NCW/x0HsUxFLsnDYBl0xtYGKYpIAJoMIzCndZaD3FtRj9AwzhDNe0bsI/BwQ3GizTyr1TGCdXKCy+NaIB+5/E5vfp+1Atqey0P8Ak7ehDSNvs0NwAItMjNWrnKEIBVg7VYs73s8nuf2rXF4uZAbXAoSuljxhpe63JM7roasaBHvCA11M2/rw+vvLgBuLUjdGSbjz245MQBTwuruVCg27RyNT8kyCtDzqJeXC5z1WSLGUUxmd2YN9tJ6/Iasx44EILMV6qJbkfJq2VmcKO/w40/KM8VqOHuZLTQIf8jGWgn6bwgady20kUobrKVMR5/vX2CH8yBxBXtjCmfPede3G74VSjUB3afEelgGPcDQlLia1r0M1Fh9eMQUyQm1zUht6iHGBBfhA0wh3fF2wRVDrMDe0+0nNqknX3VT1GrKm3sZ83xTirO5NNmKXt1SCvF9hpueC718ZnJvfF8o0n29mep33pAy62WtTkR+aMcBEsaDNGqbXfXB6SSg6eDcpc0AaUkawDlnnbPOm3/HVPjpNVngtEy94+cVBDJ9c8ceeBVGj6gcKE2RZYKRLAzxGshUKstkT4aO8i28lAH2rPazurAlVOuVkcJOfXKMMREeoU468NNBQti1Iom7il+PAxKMgRmvgJ24aV+5kSOm6oFyATQE/RAhp1TXP2jWfDhgGlXptbU+Qf11TTOCKYfTmiSVBSwwLZuCxUhEH9NxVCWBHi+OTeuecoa+L6Ma+AZhfFwi9sKOOUsQG0BT9ZApCeg6o4m0XhqXu34iYHlNxowbrnkXKrN7mPzilOALDqGnJSX4hLsSHKT4INypfPH9qanWiFAqnmJ3/E968Jk5ZSa7hRbm4OUL1W0tpfYlsHDeVnANkwLsWBd3PLIe48S/qhzNzmDgFF1Py8fHc5Jp769j2WlTgoponm/1y0YsyBI/ywxaIy1y6fVjKqJC5HqQVjkLs+SrwIFDFUEQ1dzTAbhd5+rEtvz+jgpTGvFpE/7FHohc3iRLx8F6CcVXffFFDZmRcs0VPqmOyJwdVd0x0NECEoTHBvYqrpV3+j+RAkibPFt+7ultMeBxwZY0NQ47GJafHRAg6Y+RiOw2pPUqVRjeiP9lUuAJfH5ACz7iFZ1cIr4zMt9ZSdrdb7kjw/D3JBtVPk95Y4J/iMef6MFf/qMmbf3JhC16y6BnOr0T7rw66NlaD4zpR8jIOHFErzAhJltsxcHmcHA9GoAEAjq76dHMQ6XrJfC5zKlwLLlmndHniu1CKDCQ4PXqqhMn8Fi37/tMV9fhJ3OXliNa3ZV9gBDYZ9M9MYwGE/j5cIK/tpIK1PFdhX6rI9e+MS2rjVuWh5/2vFVrI3WvzFuOVNywdB4JC137UEqxYIaZW7Q1MI/ZrhkLuAN1UUBaEzFopW4Mc3MTK2uSmTa4a8rinCM2ZbWCQQjgGgyhkN0bnrXlVtHeznx/HTGFQQtArTVtVygtTg6+GpvDEQgl2PM4eU0GOe8NuyTPROjOGNh96apt3l+9Egxu6JEY8yl0Wq97Y2GDmk16/Ki0SH/OwA34vSHFxsdFHUkHWHuAqI9V0JL8yZoNW0YASL+w26rbf2Ldm5GHq8XKyIyPoDeLpdgGT32Mf1XqKOFlj/DBbCfQx5ZFC/ifuclNbJa4nGorT/zaiFNoj1AZWBAzik56ysnfp3dGj6XEfJfcftQ+jEeXXwyAPD7XvVI/uXQ7rdKW+ZC3lzKQMvVCQDCn3QRKfQADXkXNFK66y/RLZiPg9aFBKLA/9dDIBa1mLsRgk0pQyqCCfrrL5Tur0eKPM/JFAg5wqYtpHl0wc2zAul8hDfIQI8UEFaDaySgOcSmD9hVJ1d9Ju6Q6Jlu8xwvorK/UeYQDjZ/vkzzzxbvJxILXsLqcnInl7WTswak5kRwvmg8BKKkxo8YQvTp9c1bIwtH3aKLSKTAYDNqSQPv3YZVthoOxfNs3EQRJn9VKa0uZ19E2nHl5FnbrUzl3thPnl662rhNbKBRRWfrOuiLwKx0MzsCdqIoQNhJcFjUZh5KRjWzRVPeIdoiTc4un9yzjbcFu1/bdt7Dd7q4vp9CJlYb8kFHY0KZH2/AF7LLGUYLuL68uh4kKdbw3k83zMwQO3MFRiV4cm7uCNsz0JZmFmYh/+uk0ZFY7CMX+ZkAEpoiT3tLGOVr9ILS8n1dowYK0+PF6t+QWBICSrvkjYRTPEKrQIEsmUVX893EvbQfSMX1h2W7U1XXwcbP6rV1pWhPtmoX6HfKREigcgRvf3EeUOQ0pOMQhVo+lXmhRkcHqsDVF5J6bf0xZ0QTgDEEznQVb/7TUWuhUzTH+yPme9yKYzu7NWPwyoTXA8aNlcxuXLiGHytrfxS5tjcdj2YpmWed2a/uoHeTyBrIMwnwNE/39vsEeOK4CFmdRXoFimwIBhyRJ1QZtdxBimAwCq1xkfF+zZuEOgCsHZRBFP+0gvHBHJg29HoM0/A3p8RrucfFXzylTzr26zUFmUezCi1kIHF/3se+SjhV1D2lhHdVp4hAY9O6AeBFBmwfWByV2vr23g3UJBB22YqKoJG6tA+2QHax2IXY4c7CHdzxVdUZCXUlEGJsxOuhU8NgLEvk//U0+AkflbRxxTFHQnMRnXAJouv81utGIYGIkHdCIz7eSVJMV+YWLsFU76A23y6d7u2L+zvd8Tb3kxYaA35U9kNZbbd4NeGHR6rCnYnx9ufaxo8LDSAqWsH8GRkfxqtND7VNQMK4Fh/iTLXV6aMf/v0XH3EecB99f39Mf6uWhUyNPQlIMHhG30ZzHnXw32HGWgkhkyITbSg9V1FERN7ohQW8A9tFv8OuNRZps1es95IGw1pisq42NF9CCXKBY2t5i/VS06sB5h+tkYSf5VGkq3mb6rO/AZLxqDNNSJ7KCszpyYXzOu+4yhTwy4k9A2a47CwiTzLGgRyQb06tQNY2AEpoVVNuIVygbv3e9CcZjv6ErSAfGJNuBqhHG6Kphor4JZrJmTEq0lWunte3KAXpRHjr1QwP9vym8HiMN2HKuJjFJw5+ziwZtrBhl2hk6IYac3RFXsDvn/oyBipd2mBa3Rez4l1x+vc8w8jEIYT5gDHSOyO7ufnLrGfrM3iKDAujCdFzJUshJgoCY/ryuLLieqmdWqDz2xH1fg/2t2mWzg0BViENG0bf7NdzG7qzH6y6xrHFv4uwvKqloEdyetwT2WgvcY6/U8CQIbbrEW1bYojYszxUQAnb527OsTSZMqDLxCEXoQ4/GeGceaLqw0EAHYplDC9pF3xNjXbAiW1VY6WKNFtl3Ml6/2qAL6GzPLYoMFWgR1v+fhnX6vlJWxrGt7VWiqpvWUKfzyssfud13LNxcwx4sJVz8ejK7jgv77Qo8CHm2pJgf4UWOFL+GybX55euGZeqDc6vYeDV/dzBD9phAvSE9xQqYGNXv/dEFxddPxtdHiDeFULEekiLa2svfD9qjqWOO9SA9UgIxb7ZORqZK5JWaiDjUg5tvC8EbLyX558cyChLgvliXcO/X9MdECYBpMWjyHBGIleEtTyczt3UjcBXJJroTRAVhWDPDppn+RJHuv5Cd7dccCbbOJO7EzoI4A+XyA/sYLoOxyDDVvI7oglQ9wQbyhiDZIy5KLJc75IKKwRqsllIS60gv5a53PuQ3UBnZIYCEGhiCCTLNAzqL7aZlmigdoHFfCnKrg7QDF/OP2YUH2NOMJa2mh1uutZgsqjqXIKqlURm7E998QOG4iwHd+576/UTHoa4UyzwN3jWoG+8Rt1lpuyqiRckEfr/vB3W0hrKHL+T+rcWwVtbc3dU4Rx5hsHoSJxOzTfnAyBAJStVRtm8qivv4LWBjyPe14bZ4+BYfPGiBNdT7m2d5M6c4CtiqNovfmdLTuAEQmZmdcFEPnT8cFSeDp/cuZw4D6c+n9knCFj4T3ukaI5cuIm09GzHti1B5zCr5mGukDRsjxDcAcd4OYjpLFmtaHJf47VQ4YgJbhdDyl6BAKrCqk3nHbUTnMDS/1mChN/NSqmznLzYns7tlrm6Nwp+xSz+X+Hm3FnPd40zDpiCpIGoEq30DT7JITtr25lIy/po7lqbrEBZuhuNL8vz/k2hh8d/bYxjCbJaYBASN7maVeg/wjdrVPJm5oW3ODnsoOw9pT4XQoTVp7YdfFuKGIEnphrIjCMzO8vIvwAAnHZlQ6qU+FMTjuqBgaiD+U/4RJCtrvgcUsQtW1+xeilQk4nwOuJ9dd0mtSW+2YX27tF2RrTX7Wye8GZfUBfUzAOOj/NbZYdce/LWClXdTUFpyHMH673BhCZVfFpdwKifOnDk96rclbzRJfBT7lzIYqdSyZxk21hi3j/iu9uZimdops2rzxlvqYd2PYOfRMfAM2zzqICyGF6nsh9belAWjnHce4hkGcPY0p1xFoIN+RJOUflg6k86nPpLeCuSWDkBdq87uv+ANQHhOOVqpZZNLvfsSlvdU0dP79iVGgbqZ06SQnz7Hdd0elReNH8cMm17OUHhbLlNCWBsOi4EtSgBIaCXVHo+59K1zhsTN6xScR1A/9UDl6ToSOfutFHR3dGSriRUnpYloGzyB74ozqPKVMrA9YdVV1cCTzVvGLJWpfHGPkCy0DxTsBNK0MYxWXDFzTKO3ZwUZlHZj20UEqHe3O6tg2AgME72UFOT9aPZ/errTwDVKip8OLh+9O2ZHh56oN27fLEDBqBTGiLBdfmkxbeskBq5iY38ZoCoGp7Zlirkxk7IDcKxnh2bf4WG37FBgkYtCVN7AR8h8lOsvwLurXX9mvczxW3kO8usWT6SBOH3rwk1qZBD2oJHWJIHnDKVljh9lnmNdMW7DY9m/3rqbSU1X/qmgUDLcScbWQboRIJiSL9ruDLFOdi65Qc6pn54Utr2YOQpqm3Va6SNgQIytMC+DsB9MubUqJe2wMKruIVQ0/A6XkC6S6benIZmuoSyWm2fKolo7iWLcw0aQG9qAY8hTXWzd5DhR0IglH12+KwiQSzFBeKhmQ6OfdtZYBlU7TA2pcdGCdXqoadOOko8T8y5qwGwHZsxdgGhhEqgXx0tm52V1/T93rn97CbPpbIBLDkcmwHL9Sb3r9nd1dXJ8VTNKQMrFfGXrmWk/Q3yToZXDyb07bxCInVMF8PMP/4/o4sKPM5rp5uahwxfdOVDsI9Npyzv+fdtLf87DwSeszdGmVPElV8QFF8F8rGxC1BBUqYoIAON9Rkb0pvmNJU1QunkYJHwB1Qf2F0kIF4RTcZzUv8txKsMmNNsTOyk/YQCAm4OdHUjYOh2Iw/Cp39e8vOtB7rl8+/hyLhDaONbIf2hqHI31CHSewz0B5iZYEp8KXdnX6nH9JjrRfGTWKCC0gtYbquHDbNICzwf6QjHB45+k3x4RCUxORGbZ7dozhUrSWQ4/pyM4WSNLUaxi6Kr6ThwdfARDPrc7CZZJlcCf2dBsFGfMMq4kCtWwbMWQnAikrP9epFgicqaRSvyD6tRALfEsiMamc7qGL8IAA/RwBLrADGtXRjBCNhPo/XjNyi15UD/RxZqnY0WUzRccpkoI1Y9m7q4XDrU+kBhcRDwFd1dr5UimjTQ5YBNfOWZm7fQqvNSp3Ke68cKr9coPSRfFME8iJU7murKo5Y7Wc8Hqdm0qXb02FI64e5BudV1fCoRsBusMlhaFAsGkZr3hP+o+0c4/chRVTX/CYN0eQI2FrYCatrV9jLs5U+M2qw/L27IHdAMDUyeyZBqSM15S5LuPQoUouzvL1Q/wE+pDGFdjaqmnsaACkryWJFEvMrf40Ofu9ts8x9J/vBirnWDJJa6N3OualPCrhL8atPPtuq0rUgGAk0KzX7Lv7DLtbH3sQ89Xk6+rImJZO2s3J/RKFafY5fHN7tTsSOEGMtocrp2JzuqqxsoVmS4CY/nZYZUTsnNeLeBEuntE/xTcYyu3pC0UQDaP1o77Re1PHmjLB6wDGMPBnMC+V0+dEa7xq4LhjnR1t1pF/iKfLsQ2xxGeySQcJNb1veHgeRWiXRimiLuKl23l2oQzTqYfGAtw5u8+nyksWWY4fyQBFZ2DGKY7YVa/7/42B+PsYJkv7Cnqxfig6L/p0Gom2pRlQAllbkCSXbcWJxrw9yTYPW9DF6nlBd94K/xdyOknqY++bRKnENbYKf9uCr+v990BZuew1LqGyp1n3HMe/V1SXa0JP8QQPjx/w6Zt61hZFfu0PTMWiFxFXylu2Xa73Q6iN20DR+RYWCYQzpmUFOddl+fXxzgQA1ADpAjyqpg0vxQjWUU1izYkKZvxFlrhcqTBlbwgHaI2ciVZJxoJ3513RpGkyskPPebqzs2vlPL2d/nGOn03hq+iNxTDb+iLVTxO3fVxV1qV1SLC+aYIe918c7fF5EzaaOIKVqo70Pa3njEMFwI2IQWKydtrV3121YQC+h0n3C9TaJaxr2leQJfLE/WkH7k8qqUnsr1V8eiPNYewHFoZpvy3ok553HCWLSZUrFNPkrjU/3AS+W08BReYDGVQzDg4eZPYwCmNSb4j31wzegAzO9YouZuikHz1VGz+g0qPKBcPjTvYtM0BFj+Ox/rGdtLk0dNXkLfBGAhlSz1kLaEcox4zlKzcSUPpVQ2u8sPp44B+H5aRzH3om5OHoCUcDADbHD/Cs1dFXN/bydIklSH3BoZ41zuAiGrNvGdSGlcJKeoHPsxQIvSFqnaN6pO9VObYkzGVRoZyaPxu5f3RFIvnDIybqJbU+MmhYAywHLXNOfxjzbh7N8IC03TenmCicLAO85xOSBNhYpGT61FVhjFaCbh9TWs/AATaR+g3pbyaxxjzIG2SvvepbXKi44AR/Ym3FqGsvHG7KtrxpctfTgsv01z4d8FEpqT8AL1I/noqEANcb6nEJUYnKlKZdXYbU2Q4JcFN3jg24EnMsBBaOSxZANTClPYWO2YF8QjkSgtkEpiwRkYI3CF/S1PG9+a0nz1iNIRRb6AJ9zjNDBAloXYadDKIBhQJSzo8lz7ngG8xV7CMeeO3lKBKj0njPi+4wdHWTc0/hgHAm+yThEPMdlUeIZWDBeGvhVXF9b2bxbfF+2i3hOz81i5uf5/m3vCilVVXDDFnECOTAi4SN0lV8jXy0n06QCH187BObk4pOkkRffoWR41D1e4XDrPpokH5gHhLFtT4qjHitwWz/EfxrwNSHaYktnLKJXmmC/WfwvSXBpKMUt4lw3QnFT1YR/svW29p+M/MKHNQNVwUSIKnjphRoFRkTe005ye5RC4mopIet+6Jmini7o9fXPqLKI7LskaKPCnD/V5kap/OsSIeDF9cx0FZnuax8MfG2xTksJgrDw50pgoJAEpyNtYTTWbKW7u3xzYn1TltVqDVzaYlZEpv/3RGozuYJAlbk/S8los7dF1cMhfvBubGrXD45UxMvP90udKq03isSWr7PqYH6/I82GBi2PALgLuOU5GhsCmtvhlFTdTxt9f0C9mvGE0K7tVC46vRaTRrej90EDbnJnwzYsRlcmewd6/rIH+m1uklCPLo2sWrysJ/PYbwXBnJwucXCq8oRp6qoC/37GTXaqYAc5Sn6XNa3vnoAAIvY+L/xUqpHC0mPUgSXWDxWr3UzmzHIcmjzuDIX7OKOZbv1L9rEzt8YUip+1FbKCoDJCzxtAToEgrIbE9Zg1VZnFfdIfe1NdMnB9rSrUDUvsL/vcq+P46Wx+VUG+Jm8b3PeH9y3ssy8Dnw/VynsZlmqxKtnefBjC87epQGZ3twjgMeB9vPui1Chbg+nLTBzCaFxOSH/NX0Eh9iI472zPQxwk0u28ZDEFJ8TbVZBBHot7MhYnDXihieqn4lrnVXZPfxD6uN1s2oYbKxRPK+5pPuQzfrouO0HEZcYJZsdl3youilvDPO5n6zwJMA3t4FQ2S03/o1StOtnb4JxfIJu+e4kaflH3bTkXcGe59p4nzqic5TJemCJsp9kWKx3WM2NHpJQnLQjBrhe4nDsFAJt6zRkR+BYWFmfzkfBBBFjrLrZmZxjhAop0WQ3dqZ+WGE6xl/pelKEE3Pk4yti9n/uvHdsp6h6VhBUQ7Xz9X0BFYmUwLY6rOJymYOycHHyxX5iTiHKD+qQHf/gwv4EqIAzr3VKGC0wYCTQsQNuf3K8orcYnmT47vFlOJ95EzfIMvTaXQNhOC9VvB5JNGSbbA4/VsCrD8qoTK0iQeKuFl3J9Yhfr2btBX/f4A0UyfYHNSz3ta+6QAe6O97Ne6ORcuwFHnVYuiyidSHKSAJn0UrLwIEwOk70tYSafIEaX5KT/1aT3KXNFbl5UyzSEAFBMD/CCPzM9imej/VxXQdY9BHTLp0Z8zoTOI0wjPDbVVf9yiE0si5t5UUFOXgcqvvkxYpxD+TT6Pkn4HceY9WrwbbypLzoWm2QR3cl3If+XqFsaANChpAIxtWnchMa3wYICXNl6SIUPgdffF3+EoVfp/HfpfBHcPiHIPPNLmZ/i7B6HGpZUycV3gnorIVivYZsaDTcDX+BIuJk8vt3VUkIuoyi93JWpE1j03JoB10PTzh2F+YhTmvYVjZ1yK7URrTV34Keqgdbi1G9Lo5urqD6YnRByZwsVHMI68Q12/gF4oxChR0QBPcZRHVYQ3YRKD8ZwfbkEtDHWbKBLIWJ0pTuhfIoXamdfdjPRrUIY1+ZH26Bws9IZJlQXzhHLtLNIxB5J5eyvQRSgQOPiV6lDzHZbeDkciay1oJd7pn9vz4zwPnohHus193QNfeVpY6oUjHYzAIJUGqNLVOXbY8JppoREG2uo3vK+pDI55RAa/Uf7747fqpupRxhYw32G94S6CtG5+rVInikmv4ArQ63JXH/DOvsqcqJZU6JLUN/3GGj37YTb6bdbi0Fj+NswEf9uMlueqfasbe2G7oaKuVuHW7k/YgrxWXsTILL3N/sd64g7fuxFimqTj8/akjv7gbDQX2TjBMcTb27FFG5grYO1IVGqnRJbWl+NoF6Aek3UwMcVuFrlUN4DCjEgVPYKSbZNC4oVcVWxS0h7+QKLpNiqT9RsjnsgYsKP9+FgvE9QYM34AgnVQcUOfXa+3yIauN/1QL1v+bc3iNcGKs5QAlNWU22E0WI+t0BapQZ0D/1vxgihHfVE5Xbni1mVV6MvTwkGF0V9IEAJ6Ylwx9ibUEiw0FOK45Lov1jrEqEcCg4+zYKL/OaFxuEwpBfgTXY+jzfy9NV9ArmK82AxABvg1oCe3BEcpEzAl6M+TZVjECFLG2xLFur3XvdV56OJlBSIKs+IyYnTST3otnvKhDYsutjMFx+DT4LUciFPRdLqDmpn8BqSxynAsQ+PM+0rXXoY4GPWcTaeEC0PUBdztcHhC9GGY9hRaYuRrbRvBpWIxieHq0zFJ4GXHgCEAEVSYWJwBYtKDN0Nt10brwB0jQsYTpZ/FDgI2VxOegjA5XWBmYqJaNAXuukGdX31lruJT6x6xzAx13suYiyGwlQwGMJFD2n7virZ4GC08lc5T4Z3eesZ0gonXL+myfXt2FBO+i5GPtsdlJzK4uXAClU8zdEev16HGhiQnbGVyhQ9V5Jq5DCKp0AfaWci2sO/6JAuK/uxqL+7UdadrCogXVgY+ZB4AkPYybjT5srsQWaLrmcK99aq+Cx+Qgp7qOOON+I4ZdYC3s8hHUQqo15R8DoKKIl96ATC0y+UNGHb7QIvzRIEZeYj9RChDj8M7mEHS9MB9pRM49BkAi1njDTDY6cIEWMrGReeiq6P6kmSnfj0zJVSRQGzzL0Yimb8QPYIzCkNZLemCGKEZG8FWfSmgLxFIXwNSn+3Hq8go5Qk+INr6Fsdi9g9OObotKHA5ywQ3nYeEebFSQ9i5hO6fJMuLAyFtIc4EGBHIiE4NHn2TYpQA8I+H7RDwl9FxhpJAgmU8nXyM8pq/d+KWBkPJFA0ltn7BsYx2z/Abv7119YbmBNvCsQ+hoBsSPVIlF18Y4T+d33bt3cIQP0u0MI+2/vw8YWXKCNX58JxeVjM5HyfaaTOfjXOJKfoWzmknkfqPwoKXfHd8BeUZh8nauh4Phe69WYMTJHo57uoxT6ty0JcsUWEpzgUI5mgzO4voUUMdl50X+urGkO1eSqb5+Tj/gBsawEuGxqop8az+e+ZGSpNRSxXxBgjZKJ5o1c6KaCJmfNUmt2e/ilXFCsu636jfXU1uoAnuOnLNHzXWEXu3qbDo5JD+FZ3AreMF0+9ymVdOHOweRp3vwTNTxdItpISglbehh/HkcwZsoALGQKs1B1TJOuNC/6386m5L7tVjNYUN16OglnTkNfd7P/PWJvTND1OXgn19RuyIG67cr0/Z3a44VVVeAmgO2DywCBdFphadzFqManWDg3im1wbCtT9aabrv5tZjaNB8Axgu2yhuPJodEl6ouDf9r1FbIm4AxiIYHc2eKcdcXmaOKObu0uWx9oXfVKGB7wz4N4hwWPC1MoUD7xBtEsTrUjUVstDBcIgQdqJFmuismaXDyHbGrsDsPwq7fvW89rBAwAFFl+X4c43aFY8QdC9Uiwn/w8jTM/AEJOsbase3LTmKH12U1qMuzN0jd7URhhUhoz3wTDKstmiU7ybwvj06TX9C01pBZ7o2mjVEx70QdaRs3DFC/tVnBGuWLcr/UI/r/mR003koQGYlX67oKPcgLOdYmr02RMvhlsdqcNimkrRts9KDPcH5kCq3FaTTBHSwM7DKosPNfLpemIKG6oi7Mm1dNCj/bvIUe48mWVIsmFrVB/kTMW2SS6swO1WKjRSfYgPO1ZXmQeC0u+GkmbuCuCL78gK3Ac4Y59nnZonoKOMt5bp7i9atiiuUolSDA0q4+uA7d33HKRuokxTfUxkg8nDP6cpgqRi2P4RXCDEPxqCZ9M9W3M5ng+nnDMZOmWhySvtBDVMPSC7bcxIWU3qk2S8Cnm8nSL33RfMJ+RuiMRDtGJx6l3170dHfegAOke0cwT1z3i13wt7yo34PTCcRvcXsAXFjNb1fpeljcQbSjmWj9mlMSZLXe8BMTerF98kF9o6uc25/DqyqoMA8MDPkR7w/1mQOLcqX969DIn/hFWHlAQ5g13SSESFsPcvMfyPG8FFaX272I90QQUv8HyO0d206i2vl9tXFi/y1hMhlUZy/sMAWhPE9utNSk0RoqZqfkHFvwsPVW8eKY3CdrhPscjFQ1Rx6sPk+hJS5BQR5LB8hYRoErgTuZUy+0oAr/KDW7uYYN/NsRIiVjC2LJ81Au29N5WKjSMZxv0oSp7v05FLv9mIfeAocPkMRydWRVSdWo29hCLeE0Q/aBgMOFOs+N3Ywsg+TEetMGiLpNuVLNHPuyjUDxvB9f6SlVB7IGKmTtjvDqUXjMn7Uskkiquvr6LIaudK+zk7YPOCwxf1bx6S29ONO8p+WdtUFWMK8tXrcQ7lG6Nk3aECYR0XrMThokSxReBZyXoD9f/SJ31qna9Irp4AglFgT0hSivOTKUP86J4e3RATWUftJfsTlsObd7SHlqoGKf1Whb1wNa7ZJSTLAvw8LVQlsTIDRjfs+LvyJUp/l97iuHFBlBJ/sToeAPaWxfRHvwkkDP0YNAqfa+8rAVtX3LteR/437Be2Dh1sOAwH+y2p3H8lwH8MhikSwQrnuhrXLb+93YJIsI6aYZpkUW0cOmsijblV16mVEInsOomkiYI4ZExN+yK6oKgfHqnKmigS6Y7TQYY5DifbY9E7BJkp4Bm3rctqiYgibl7fOCpxT4INNJUBp+BYO0lGaGZC1H5ybdC8RxdSx14TrMJwV/k58E91IZ8MC/Ds8jSZHp0dgyMZetyvc+l13fw+Kj9sx0eFw/P7ROZR5t+b5KY6S9wFHHCReoHzDABePo8jLwzjeLiS3fdk5Eqtp1SUDSKZ1Ii81q8VjjKTBqHLJeDP9nFFkIhbY8C71wAU7MPb3sShnD9TX6QjLE+OLd85ntm1DGd7LNMN5YB4p8FgcsDOziz0KuuKBOg/nzOz1dw9Bz0ICD8TQDQYRLJgazOPLT95v+RZfPB7gK9KmJAa9wfhnUOCFCChnjSvkWQWKwBiHGuj0kc0X0UWkkeWgjJeL2fmvnBA52w+BER+Vj05FfNJnlG6zjqkoC4WlUzMiF9woWoymCsFBQPVDdZY4nqkWfElH4YLASYxuaDDn8gh5+Zpr/tUXCbhVrevjX/WYIuB2jLOV+A7PZv3iU/lvvXpNIAa9mk+C+C3XVXPXmo/Afi4gC5tVwGOXN8OVjzxpIZF8UiN4kiF/RVmLuxPwP4Vd/YGgAVbX3VMOCrqaAMZ8rnU7+F9BK6wsBSerWy9aa7kWQ9Ht2RFFrXN7mbEgogOtGwdlmbNK0cn+X8Ftv21olaUnDB7ZXBbuhStT756G7yoIdhQ4XMVgKcsFzcG40MXNlzx6htnCZpI/8WYVnSnkEwQt3/+03adsveSJH1DOZanvwCbLKureUXrkRuiSpIhY8uOhdInkcQk0QN6DJ7iqrDItMaNn24FYLQqdFNVXvu6XVYwwW+mGtxtr0I5BfGJTlpyk9EMMD8o6lbohN8Vtbdu8w4C2zkZsC3Jd3cONJ7AXjRj1vtsmYJ90iTMw9qhs7Yz50Qyt5gOQ91oeZsmmCVXF5YQlSlH8ZTxLSWmeZeOO0IzbNprezfOuvOFqSbDhWFtzhP/oQWTqdZ60THeY7tjFIY+qEJsFUEzpDenrVBRL6KMhjdANZLr/J60nF18P0VyFcHCvlUu8C8wfY6JCHYES5sxt8st//5DVdRIuJtwhkNoC0MxIGa9wet/5xKf1VslJvGNEe9FTRGfLGqHFCSnRlCM5/0Kow5FwSvvEfjleHWbaREAyuiXi5u2Zjovx3vGBQXGXxjZ/w0Kr0fc1io59DqEiIX/+hdcYiNKmlPaoCr+xGxVUPqtXI+hugA0nNLzAi2onq5r0D8gxQJ86w/6QXUgIZvFD+mBd2Yv1yict+ItE217W9laUYXQliSaln0CYTfjyAOpM5ICDFDl0kAQmZV0tDuFmqiXgxIPk8jk64VhjWbHd0iOc2FXFPySGFC9olVDuW6yYE4MD+OZdhb7ihPYQfXqZU/Ej85B+Q+ih0TUwWxVoZbl1F3wPKt3TPhCfRy32WQrql5gGU6rUz0TwdW4hySAlu+18/LLdHCJzlc8Zly7nbLCSUO8+tAY8PI8ajZkKHAyWCkvAoxsMZcs1P3HaCI/57iL03pm+KwX9E56FyUgI7c/7CmmR+vkH1n9UHQHJHq9Bjkdb72G2GU+gxA/O+G67rSGtIlAAb7c7g8aZUY/pgHuG07kMCvKPSyv8lCWiaGb1cj4+MnDRBKE9EAD3K293mQOmLyxVwXeBs0hbfh0HxtEqkb+1hC9p47/LpzVoHX4JR0ADMGKdLTCaRvWytHdt74a1Kxno+bKOJRdyVh9GfFsJIulpVxoo0lbnQiB0DHMZRhDfeYZu7xvb8nf4948h5aN/1x2dIuC83ks9soMka24Nd18YdM7+vS/LePgh6GzDIceCCXqqGvmBTChMg1MrT3sgyKlcq7tlvklu/5BuqqI0GS9adn3HHgJjwhdasTtZ7UcafbFFoaVaj9H1vEf67QknXGOC/SicnkO+dfJ7mOFNCrUiI0fZnr5H3gH5t3uHE3OJ0/qmWA6gFlgrGunjRasfUZYwC+y9zDbdjaSv6wkRlJyscKxuLOAGy34ogRKcF+6H0EXLQVoUR+lu6yh05TyuNEXtGDdKOLrr4xphyrTVfWaDZH3oJKBoK5aGHhU7DZsMmYYqYOB214hztfWCrJo0f8pnXMU6invY5o0ouRrrBkov8K+BlyEw8yVOHmFlxB3SRUIuvtf6dpb+A6+LiovLAoEaDHlRoEpIrUdqk0Q9uKTbfkSCsN26oAPHdrZHcXE77QqDRllpa0Sjw1qm6vQtq3e8hitNiepNF86lAChLBJyGcnz2ko0WuT7BzRXoq2uRg67wByg/hxXD9dT4M3SEmhmt19faJgtivZjiXGU3LQCDX3twbF/QuTPfAdTEwlwvUaqr8PJ1z/FGV4KQj6/FPJJBBATqM4i3qCBBGh7bXJ8TojGJOjK8xmJd6GUofqb+8HXrwE+9EV3ZOPbPQJ9swg8vZxoJHCOQ1fOLFi7Vs7ztfA2i+ykMcARDPJiLZDkIdwFyRurJRIRakNo4fHTc6NfgFAlwzFSOF3suNkCWs0awmjJkyNXdEIKq3sT5AsMGNaXRgZIJE3fZoHQ1pVdUyMtV7GJ91MEK4uqg+VRjopYTbPIbbeulq2njZ/TSzzZThUg0B8Q09hxlLBNOi6tctF5UNZSNfmoN0Yi7sbroFlgrdGnHdu4/JjbeMAdaCCY02IKyWRzFyqYMXbjBi9fWCyRt7qDQveoZ/WDL57Dh2z+PkQfxUQ/zWryQS5Gx0l8cZ0sdiUmndtsjDEw6XEkZt4i7pekGltwL6X9H0k3GGT4U+RLi1+6FjJNugZCJwCQXgwOurX7/B1D6JJQFg50Waj2ipwDJcaW+fzLuF+byzfVI2Q5GevA0qrEh1HspID8bPgt9EP+BS/iocPLkJX52wAl951SJd1Ne/oGAFUv5C3HOqtcWQLh/cmApRGtPcw6Wkapwpo8hGwsKDYHBr54tUBroqe6qCg7xenyoYIq0D/S8c8XmIFJ/I3AE5GcRZUsBLSTEIVarvXvyAyJQeBWPRsvE2tTZtMGuxS+20Rqxy232DG7lmgrjLeyY25t+evmDtlS6y2roI+aEoBuGeycqPaoIjDBdd3UnEFNU5U4nkoPbJjMBS9JgEPuLnX7UAKezEb7vUbl1Cj/5TwSXjgGYKpgODs2hA7SvJ1DSuftB29WG6pEqjt4mKHw/cOs1X8PnpEQ6XUIeHSZkM0w8UCWrHJxVFtck/Xcsg3dtk1crzAoVzwO1Grjg731jVNNJrQxk3rV4WdBBfpHCwG7Kk0d4sAyLrxDSOiio6aAnghCvsWRNV0Mz40Fzb/3OzExlNHEwA9YnCZi4nuwbDJiO714okB8QbiRMJRkPCfdU/r0NzytET8xtpI7s5E3Ol8yUrWJj1DNM7gGsxeUG7dD7wGOpA7IYwqWG31525E0y8ZIytZknSLcN35uDHJ8Eym6lqdxRdg/uHLpxUk7SL6Dn+TIe+eii3ubEj90lVL4c2joA5puYslDoTaWrsfEHJ7iyrKGa7g5DHWxkcB995Zk5coL9hSowZASKdWMpQ0HR2Dv/ZnDkO523WXlF0F35vTkIxtjjn48CUXMfzGjmEhKOWACYonLbikFqpvQ/VM0XTPSbmQg7LNw2FUN9itOTb4aOaCb74LC88F++KJ4azDVYVpxXC35bfsqdgK2lngxfFqhMOGEYe73c8l9Ti5gli2PejI6Hm0y90SygCRfiI6fOa2qBoMKOnoLyW4M051d/uz/Q3vRIgo1P0Q+LmgPlLrKjxxWE4Bz8pS3H0OwC4Z93RPMcTCrhAWmxmwSWNNndKUdI+0Cbkfl5NFeccJxVvBNCDiocwbXMMekEFPuotzsvo9lngvUru3K8eFcopeLEGL3jR+UWaJHrk2TrBBkQ0LYWzBJhp+607Jupq/ElEu26yMPKXR6iXUkbPYK8X4grUI47PUy+1LtCHadoazQVT3YrnDkjVausHVJuhSkB8HGf8uvEfustVvOxc7yxkqMj/ThLtVCXKUFbo514Q88t2deE0aslFeC2QXc8dd5MfIrdvDwRXeYAidIUcj4VX5gt2Qcf/54oL6jplPcFRBMhLBc5d0GzkyG+TLqswZywo6duCrgEMf0KJL0FqUoAAsAxpznuCSr2YTMBXza60MnzBFouGOqECR4D2/6+fbtJOUWEuuf3i8zUQqdJVuQHbbOmTX/TWVw14Nbp5gzk3pi6SdGS56VW+/tf30XRCWgIUvvxcIdWWU41PDSyKrTiGhnuMK3H/b4dEm7DaK2lAm82X+Kgodm1uebg4E0ZvcN/xFx28XHAv3hFd0JqpIyLXcLa+ZJMF3cOJqINMgJ/uf1ZZBCHNWbY7AHPm+caqMzXDesYXx1J6lzFEaVuOpTSO2alVO+QxSTNsspNCdV9P4VrdtmCt8uthsLAkDlJuOdxKHzMNcg0X/f+pHKZSCrWEfku9D65SwSVBkTi2pwsK938lkTrSxPJylUfTwMP2x0FSfI2/nVVBJiZlB5mW2JCdW0/gGxtTCfxdIIzg2FvW+mLs0WTZfazUrMbQFFuquta+Gb6Gb+2SPTAaoNXGJPh7K7ZL6VpUTrIhzizjFM0uQXa9r98cf5iVRYwd+rZOA6igLquS9HDW9PTCovyUpCMiaSBVGpaT42g+oRg189L/KBHkjs78sOXhPEq6GW4O9BRotmFpBJgW5MhszrALMyQ0UoXRu6PtzwxBM6fZfcUZiC1EToOB1DBnViKwFtCLUXiZWQqZubJvIniUFR0iltSENPRFEystHmLOyusYIsyFK37PGaY2bC6GuSkAKZ4uC6i+qmPeroh3Q1nygH8FXRZsrURAnxmupwMNuz0woWtbK+y5X5L3hypaAU3Hbhj0hJlJkkpZtplYAhNKuHByrdOn2A/+0Ls1kn++XZJoZfM//Ig0i3PR/d/08dGitolRuULJHrdZvVsGHSIj8XjQZqGKcMlI6C20OrU6wytTx5GuINb/6XglyLCLUAl9vPzIz6xay+tdR9FywQhTDedF/Y7JboQl7/RRSYk35ungaCIDTdh8OwqMJj/uFKrWYFRSJ9GZyU/trS3+R+1mV8M28KGNBv/xe/751MjEaC5bex/tcoO1IiM22vhOdFQe591EVGYw6NwJw2Sfk9nFnZFNGLEVncVbgH+7KE142Ekx/GcXUHq0AxwdfLx/cbRek2T/Vk4Q3vkYOSXmk6FqbuKddTv/z/Z5EF4LMV0OrJvIkepmPTpHX8PP1gEMn2nwsd6azE0ql2KO6nh1SN5UIFvdtJFuh6f2I2NsBkbG6lpQ+y+zUIGjn4KYqeSS5bMvk0rrADmR5HjxI9H6VH8GKWkThx38o3AzcMP08yelp4GZS1tJbiuXfLoOFjBoyFnf+0vOmXmzrbn+xBtIoWmBT1eP1E1tsJGOKLlLv42nMdd6glcxhx/NkK9tInZgYkrlz5q4ENQqbwgYAZe6a1fcKkPWXpqJLDMSlfFtc3f5E0kfYxbDYKY+rH0PZH2RPzrpOu6N7SaXrNoDPFw+iST6e6OeG10Hw4I6QzPPTY4yqFTP5/ec/wXu29bVhVcNgnYPddBo8dh0682XdpSMlLzJQez88fb56smkUlxIVpCBAojB/UlyTVtxEk6IDD91mVPrILdLHX5epz4QXUWx2VUOH2zpV2zZHIZZH+0RVupo13g9hirIzGobxfYTAm+no0p572sxAjUCgPiMC3Zz6Ks+qrWLilGMIhMYrdKk+r3H5PxyN81BPx7vErZwuSfCk3PptawcEvnDaP04XgbZ1udyCG45MUOzqdW0wBxj1MVyP06NU5n6ZBU626RFnO0qsCA3oCiTbTs+QAH3QOQ9sQDGqk8ylCzVpDSrhvctRwJBw2as924DZP8fhCTI1svc/c8+LJqsIfAR6ZdzIBGa/zhBTrDSZm+zlI4zHK0UZDLVW/DM0SXy05cfhtgdWIN2mXrSsDy45pDPwuOi4x5NJVAfLRkKAZCF08BS8uj4PfzX+slOb/sCmMgRt5VKIUdKxkkbTW6fzSwruemdIX+N/CPpkKr8TAg9/BpD4Up5thQWmO35GI3QFwZsz8yzHsqLc+ooQ1p6Uf31Cd03t6K1zk7yEet2EzcnZOOBliw5wZC7pBAVCZ31nKDWBRb3G58C35NZ87AAgQTLFF5XJ+VX4ADPVfrtIbB/YQf5ok76Te6Nybei+MPH3zo/3oG74+Y3J3ShYmigN4TvU9Jqurn9n9MslVyd/nil3pfRv3JElLKYTPe3n8sQl/W+pvwFayXEZSbiyEq0CKC7yQKER4dFkU9AciEMAAI1q6mbgQSc3uZEwaKTQvenTv7Cn1V0BFESuhCAImxmtCiSLtFHDwaoBXweoFp8h3lzMVYUatT34LuZ2Sfzjm62iC5loxdxydV2AdYLeX9tmmln0ineBqUXB5rXYchRxPWvZzGGQDhlX36k+qd9J32F1FAdWxrUUducpzEv8ePpEKXsLhGF++6g0Q2m2yADVX4IVxgol2XfiQiqqTqh8fmALto5VRrTfC9rXIAAJcOYV/xhLD6sBNevLASLGq1Ssq8FBHRdaR8PZ8jZkvleO8gXov9XEaG7Z0CXaiIuG/Y5PhvXFT0pDs+r4PaLi+c+xIhZX3e4sjDnmBzmy8t7eeGGPX6dQhzvTfV4qcQzXqytz10uc+WMX08Mnr2fIwaND97KbqXvX9DlH5DWptdFOMeXq5Fw4dhVd+VAWYi7N0g/4/0PI0KmYoupNbsL3jTUB7+hF3fkY5/8o09HBxJ+Y45hfElxpluO86Uwi4fQivFeKvSGIzLlALjjcuCkljFC+VbY/NRv00Z0Mv+GakDsOHedBez5WlNC2f3CpzHfU5avFpNBQsyPBnJPaUfLrMje9P3qhyNsoMNBptOPSauBK2zw5mvw97BV1+4UlgAaORB3lLW6O2VYkVTh1U3WvTmJcUwkOn5jJaKSrlDKd48XR+il5vmmYrn5pdrjMTNTYMrQKCBAGrOzlqTuuGDE71DFHOlBZegUiRDOejyv1rKwePFzqSXjsbmYz86HKu3IF1F45stD3yqRudxHwXUl5rIr67I6TRnrx0u+BlD2+wb3A/sIqgqGEVm2EM/MtGCQ+KlWxzhi/jTKnVXE+V3Yb3+ub3qEGnXmj0B/zvVmEYiw16mGYgq9gXw9bJirxOzmP2X5Dd1uDWd1oJcKjmzr4aEgTT6qQ5bd25Ry/TxxB3bU1moqHdM84naQ4M48q7z94kOh/5Zemxz3a5a3Sv8d3rBLnJY/QuWFzXnBBEOxYNlryJ03VKhvRYFqHKTiEZYUz74AHBisnwoJa3qZ917dis5C3ld9TUaEZjsVeIMZhOFBe++47d8P98O8fLhWZeMz2Ti9E2x/c7OfPPv3kTI7Aw6mPHAwmMGf1PgtQziz9Whw/9IPSHsdnvqO4SUI747u3jZpola/fhKMlDiIjNc2o0nYQNSNOvQZTqq9kjei3gLM/AwFD/jLaE96RZJxg0RhyAeNS5bd39DyYJyNAGwZe6HqnAZQMtXoditaYp03OOf/zwskxI2hWvkqGwQzKIhlkb2uZBJMYBfvo4juVEL1BoZWKXfngUCkCCLeXH7hIdnjC+yHBU2pGfkZS2Zka5VJNXwx+0wG4uZFOd1t1ftYfvHh1nR3ej7ZHjtAZb5ZWrqEuyYW5y/0GfALD8tJ5zTDzQNQiXQmFv4lNr3KAXJGkLmlvD3c1YjZ2ySaLmzGijr3lqpfK4nZxeV+K4KapskbI0qI5E+SusD4trwO0Q1gopVMQt0IuWs0F4mZf7xg5Ly24Nb4P1Kqy8mG8fwaYsB6CPvr8WYRWqjypmTTyKuou5wlSOUq2QRyVQoBiEGwzUSPHduCDhxVGsZZJUokE0fSfRKsHDMpDVfMcnbzyUVkeBRp9q770sP1UgWhP0Ym6abxDHA1q/MuUINeJbyINpZWkaK80kPVuDMSifMgWnp9Hu+7HsJEseNtNrPGWzSmclAL7bQhkdcjNKRustrL1/xSDNW1/QGG3J7OIX95UmwCNLweHK1PnJvry1bvrgHRqLRj4bs4wepeLZ5SsaoKpaX1O0M/47g9xvHMKvUSa81F2DbQKSMgQieFozYAKlmbKlQe95h19xTWVJl3mpT50rfTef1KyORxWxWgwtueCsEXGnfkyoHiLQA+toUmjuxbV1zjRDOc5Pgy4W9HfBKV3A3i65nVt2RIA00dtiVon1+JpYxTGxMb/PtzR1Q8yB9huLYDMToKCM8XC+lWd9JSG9AuA8vupJsgYat15K0/1/eeToSlLQZuE4qD7Poq5Pq810U9A8K3/8fuWpPVpSHo6+r6xahrjs9+exhl7Px87CHrs95cLS9RzCqLnRQ7KDqow+FrrHXkjpKDPrgoycNh2cCA2/HcV5MGBWnA4J6tNrjb74V3gJcvqd/QhdxM3xmS4AQ","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"2afc0e94a7fc480e44d268fdbb0ef6d21075da3b","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file From 31f5b662a50b6f0300a2487a3a395c24622c5734 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 05:19:47 +1000 Subject: [PATCH 70/95] fix: reject noncanonical webhook hosts --- Services/WebhookEndpointPolicy.php | 2 +- tests/Unit/WebhookEndpointPolicyTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Services/WebhookEndpointPolicy.php b/Services/WebhookEndpointPolicy.php index 245da98..da34a32 100644 --- a/Services/WebhookEndpointPolicy.php +++ b/Services/WebhookEndpointPolicy.php @@ -106,7 +106,7 @@ private function parse(string $url): array } $scheme = strtolower((string) ($parts['scheme'] ?? '')); - $host = strtolower(rtrim((string) ($parts['host'] ?? ''), '.')); + $host = strtolower((string) ($parts['host'] ?? '')); if ($scheme !== 'https' || $host === '') { throw new \InvalidArgumentException( 'The webhook URL must use HTTPS and include a host.' diff --git a/tests/Unit/WebhookEndpointPolicyTest.php b/tests/Unit/WebhookEndpointPolicyTest.php index 42f7ae5..0263631 100644 --- a/tests/Unit/WebhookEndpointPolicyTest.php +++ b/tests/Unit/WebhookEndpointPolicyTest.php @@ -50,6 +50,7 @@ public static function blockedEndpointProvider(): array 'plain HTTP' => ['http://hooks.example.com/path', ['93.184.216.34']], 'credentials' => ['https://user:pass@hooks.example.com/path', ['93.184.216.34']], 'fragment' => ['https://hooks.example.com/path#internal', ['93.184.216.34']], + 'trailing-dot hostname' => ['https://hooks.example.com./path', ['93.184.216.34']], 'loopback IPv4' => ['https://127.0.0.1/path', ['127.0.0.1']], 'private IPv4' => ['https://10.0.0.1/path', ['10.0.0.1']], 'carrier-grade NAT IPv4' => ['https://100.64.0.1/path', ['100.64.0.1']], From cb677ddb5f7e5f961128425b06c54b598eb79e3c Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 05:20:25 +1000 Subject: [PATCH 71/95] docs: refresh contributor knowledge base --- AGENTS.md | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 09695e3..d70e7c4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,8 +1,7 @@ # PROJECT KNOWLEDGE BASE -**Generated:** 2026-07-25 18:23 AEST -**Commit:** `66a840a` -**Branch:** `dynamic-slider` +**Updated:** 2026-08-18 AEST +**Authority:** Current reconciled successor source and `DECISIONS.md` ## OVERVIEW @@ -17,8 +16,8 @@ DynamicPterodactyl/ ├── Http/ # aggregate customer and raw admin APIs ├── Listeners/ # transactional cart lifecycle adapters ├── Services/ # reservation, capacity, alert, setup, audit core -├── Models/ # 4 ptero_* models plus AlertConfig observer -├── database/migrations/ # 10 migrations, including checkout identity and key normalization +├── Models/ # 9 capacity, reservation, alert, and lifecycle models +├── database/migrations/ # 21 migrations, including durable lifecycle and encrypted-key upgrades ├── resources/views/admin/ # 1:1 Blade views for standalone admin pages ├── routes/api.php # required from boot(); /api/dynamic-pterodactyl/* ├── tests/ # isolated harness; see tests/AGENTS.md @@ -42,20 +41,23 @@ DynamicPterodactyl/ ## CODE MAP -Caller counts are CodeGraph static counts; Laravel events, container resolution, policies, schedules, and Filament discovery add runtime edges. - -| Symbol | Type | Location | Refs | Role | -|---|---|---|---:|---| -| `DynamicPterodactyl::boot()` | method | `DynamicPterodactyl.php` | runtime | route, policy, observer, listener, schedule root | -| `ResourceCalculationService` | class | `Services/ResourceCalculationService.php` | 41 | uncached panel reads and cluster capacity snapshots | -| `ReservationService` | class | `Services/ReservationService.php` | cross-layer | cart, login, checkout, and provisioning state machine | -| `ReservationConfigurationService` | class | `Services/ReservationConfigurationService.php` | cross-layer | canonical payload and fingerprint authority | -| `AlertService` | class | `Services/AlertService.php` | 14 | threshold checks, delivery, shortfall notifications | -| `NodeSelectionService` | class | `Services/NodeSelectionService.php` | 11 | best-fit scoring over current capacity | -| `ResourceQuoteService` | class | `Services/ResourceQuoteService.php` | customer | complete-vector checkout bounds without node disclosure | -| `ConfigOptionSetupService` | class | `Services/ConfigOptionSetupService.php` | admin | transactional setup-wizard writes into core options | -| `ResourceReservation` | model | `Models/ResourceReservation.php` | cross-layer | shared API, policy, service, listener, admin record | -| `routes/api.php` | route entry | `routes/api.php` | runtime | customer, checkout, and admin route groups | +Laravel events, container resolution, policies, schedules, and Filament discovery add runtime edges that text-reference counts do not capture. + +| Symbol | Type | Location | Role | +|---|---|---|---| +| `DynamicPterodactyl::boot()` | method | `DynamicPterodactyl.php` | route, policy, observer, listener, schedule root | +| `PterodactylInventoryService` | class | `Services/PterodactylInventoryService.php` | strict complete panel inventory and connection boundary | +| `ResourceCalculationService` | class | `Services/ResourceCalculationService.php` | live cluster capacity snapshots plus local commitments | +| `NodeCapacityPolicy` | model | `Models/NodeCapacityPolicy.php` | administrator-owned CPU and overcommit capacity authority | +| `ReservationService` | class | `Services/ReservationService.php` | cart, login, checkout, and provisioning state machine | +| `ReservationConfigurationService` | class | `Services/ReservationConfigurationService.php` | canonical payload and fingerprint authority | +| `AlertService` | class | `Services/AlertService.php` | threshold checks, delivery, and shortfall notifications | +| `WebhookEndpointPolicy` | class | `Services/WebhookEndpointPolicy.php` | public-HTTPS webhook and DNS-rebinding boundary | +| `NodeSelectionService` | class | `Services/NodeSelectionService.php` | best-fit scoring over current capacity | +| `ResourceQuoteService` | class | `Services/ResourceQuoteService.php` | complete-vector checkout bounds without node disclosure | +| `ConfigOptionSetupService` | class | `Services/ConfigOptionSetupService.php` | transactional setup-wizard writes into core options | +| `ResourceReservation` | model | `Models/ResourceReservation.php` | shared API, policy, service, listener, and admin record | +| `routes/api.php` | route entry | `routes/api.php` | customer, checkout, and admin route groups | ## CONVENTIONS @@ -64,9 +66,9 @@ Caller counts are CodeGraph static counts; Laravel events, container resolution, - One pending hold is keyed by `cart_item_id`; reservation writes use transactions, `lockForUpdate()`, and deadlock retry. - Tokens are internal/admin-only and never appear in browser, cart, service, URL, or audit state. - Controllers validate/authorize then delegate. Customer responses expose only complete-vector bounds; raw node data is admin-only. -- Quote and admin route budgets are explicit at `30/min`; there is no customer reservation, independent-max availability, or extension pricing route. +- Quote defaults are `10/min` per IP and `60/min` per panel, with validated administrator bounds; admin routes remain `30/min`. There is no customer reservation, independent-max availability, or extension pricing route. - Provisioning must call `beginProvisioning()` and `completeProvisioning()` around the external create request. -- CPU is never treated as hard node capacity without an external authoritative inventory. +- CPU capacity comes only from the administrator-owned local `NodeCapacityPolicy`; stock Pterodactyl node payloads are not treated as CPU-capacity authority. - Treat current code plus `DECISIONS.md` as authoritative. - Record live work in `PROGRESS.md`; record newly settled architecture in `DECISIONS.md`. @@ -101,7 +103,7 @@ Caller counts are CodeGraph static counts; Laravel events, container resolution, php artisan schedule:work ``` -No extension-local Composer/npm build, lint command, or GitHub Actions workflow exists. This `.tools` mirror has no vendor tree; run PHPUnit in the deployed Paymenter tree or its `/var/www/paymenter` container. +The extension has no local Composer/npm package. `.github/workflows/cross-repository-integration.yml` assembles the exact Paymenter companion and runs Pint, dependency audit, PHP 8.3/8.4 SQLite, and pinned MariaDB 11/12 tests. For local PHPUnit, use a Paymenter vendor tree and set `PAYMENTER_BASE_PATH` when the extension is not nested under that checkout. ## NOTES From 7843e2a670603e54d2dfed035db7251d972fa3ff Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 05:21:21 +1000 Subject: [PATCH 72/95] docs: repin corrected Qoder checkpoint --- .../en/content/API Reference/API Reference.md | 24 ++++++------- .../Architecture Overview.md | 34 +++++++++---------- .../en/content/Core Services/Core Services.md | 2 +- .qoder/repowiki/en/content/Deployment.md | 2 +- .qoder/repowiki/en/content/Event System.md | 2 +- .qoder/repowiki/en/content/Testing.md | 18 +++++----- .../repowiki/en/meta/repowiki-metadata.json | 2 +- 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index 0ddc0d5..cceacd3 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -23,12 +23,12 @@ There are no standalone customer availability, pricing, reservation-create, reservation-confirm, or reservation-extend endpoints. Customer quote failures are generic; upstream bodies and internal exception messages are never returned. -[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php) +[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php) **Referenced Files in This Document** -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php) - [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) - [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) - [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) @@ -82,10 +82,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -124,7 +124,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L17-L22) - [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) - [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) @@ -141,7 +141,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L17-L40) - [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) - [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) @@ -151,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L17-L40) ### Endpoints @@ -190,7 +190,7 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L17-L40) - [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing @@ -229,7 +229,7 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L17-L22) - [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) @@ -313,7 +313,7 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L24-L30) - [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) - [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) @@ -343,7 +343,7 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L32-L40) - [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) @@ -378,7 +378,7 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L32-L40) - [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index d954bb8..5cc0df9 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,17 +2,17 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/DynamicPterodactyl.php) -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/routes/api.php) -- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Services/PterodactylInventoryService.php) -- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Services/ResourceCalculationService.php) -- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Services/ResourceQuoteService.php) -- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Services/ReservationService.php) -- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Services/UpgradeReservationService.php) -- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Services/WebhookEndpointPolicy.php) -- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Models/NodeCapacityPolicy.php) -- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Listeners/CartItemCreatedListener.php) -- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/Listeners/CartItemDeletedListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Services/UpgradeReservationService.php) +- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Services/WebhookEndpointPolicy.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Listeners/CartItemDeletedListener.php) ## Reconciled Architecture @@ -136,9 +136,9 @@ in Paymenter core. For implementation-level detail, use these versioned repository guides: -- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/02-SERVICES.md) -- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/03-API.md) -- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/04-EVENTS.md) -- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/09-IMPLEMENTATION.md) -- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/DECISIONS.md) -- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/PROGRESS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index df56bc8..c4be42e 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -17,7 +17,7 @@ `SchedulerHealthService`, and the audit/configuration services provide the supporting policies and operator visibility. -[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/02-SERVICES.md) +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/02-SERVICES.md) diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index e9d1190..a9e1101 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -27,7 +27,7 @@ by the cross-repository workflow. Before enabling dynamic stock: The API key migration encrypts the stored credential. Customer errors remain generic; detailed upstream failures belong only in protected logs. -[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/09-IMPLEMENTATION.md) +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/09-IMPLEMENTATION.md) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index db1ed8f..665cac9 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -15,7 +15,7 @@ companion lifecycle. The reconciled extension does not register cleanup, reconciliation, capacity alerts, and scheduler-lag checks are registered from `DynamicPterodactyl::boot()`. -[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/04-EVENTS.md) +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/04-EVENTS.md) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index ef49313..0da8aed 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -14,14 +14,14 @@ process-private named-memory database and rejects inherited generated URIs in child processes. MySQL/MariaDB tests may use only the explicitly named `paymenter_test` database while `APP_ENV=testing`. -[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php) and -[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/TestDatabaseGuard.php) +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/TestDatabaseGuard.php) **Referenced Files in This Document** - [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) -- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php) - [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) - [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) - [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) @@ -86,7 +86,7 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) - [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) @@ -97,7 +97,7 @@ U --> AC **Section sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) @@ -142,7 +142,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -361,7 +361,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) @@ -383,7 +383,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -425,7 +425,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/2afc0e94a7fc480e44d268fdbb0ef6d21075da3b/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index dc76c1d..0bc3e97 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"2afc0e94a7fc480e44d268fdbb0ef6d21075da3b","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"cb677ddb5f7e5f961128425b06c54b598eb79e3c","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file From dbea10d8db77b0119d03e0235b60cb0bc10067e7 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 06:01:01 +1000 Subject: [PATCH 73/95] fix: protect alert webhook credentials --- Models/AlertConfig.php | 1 + Services/WebhookEndpointPolicy.php | 5 ++ ...08_18_000020_encrypt_alert_webhook_url.php | 51 +++++++++++++++++++ tests/Feature/AlertWebhookEncryptionTest.php | 49 ++++++++++++++++++ tests/Unit/AlertServiceTest.php | 37 ++++++++++++++ tests/Unit/WebhookEndpointPolicyTest.php | 2 + 6 files changed, 145 insertions(+) create mode 100644 database/migrations/2026_08_18_000020_encrypt_alert_webhook_url.php create mode 100644 tests/Feature/AlertWebhookEncryptionTest.php diff --git a/Models/AlertConfig.php b/Models/AlertConfig.php index 59aea44..51e3003 100644 --- a/Models/AlertConfig.php +++ b/Models/AlertConfig.php @@ -31,6 +31,7 @@ class AlertConfig extends Model 'notification_emails' => 'array', 'email_notifications' => 'boolean', 'webhook_notifications' => 'boolean', + 'webhook_url' => 'encrypted', 'is_active' => 'boolean', 'last_notification_at' => 'datetime', ]; diff --git a/Services/WebhookEndpointPolicy.php b/Services/WebhookEndpointPolicy.php index da34a32..b86925f 100644 --- a/Services/WebhookEndpointPolicy.php +++ b/Services/WebhookEndpointPolicy.php @@ -16,7 +16,11 @@ final class WebhookEndpointPolicy '172.16.0.0/12', '192.0.0.0/24', '192.0.2.0/24', + '192.31.196.0/24', + '192.52.193.0/24', + '192.88.99.0/24', '192.168.0.0/16', + '192.175.48.0/24', '198.18.0.0/15', '198.51.100.0/24', '203.0.113.0/24', @@ -31,6 +35,7 @@ final class WebhookEndpointPolicy '2001::/23', '2001:db8::/32', '2002::/16', + '2620:4f:8000::/48', '3fff::/20', '5f00::/16', 'fc00::/7', diff --git a/database/migrations/2026_08_18_000020_encrypt_alert_webhook_url.php b/database/migrations/2026_08_18_000020_encrypt_alert_webhook_url.php new file mode 100644 index 0000000..c28f760 --- /dev/null +++ b/database/migrations/2026_08_18_000020_encrypt_alert_webhook_url.php @@ -0,0 +1,51 @@ +text('webhook_url')->nullable()->change(); + }); + + DB::table('ptero_alert_configs') + ->whereNotNull('webhook_url') + ->where('webhook_url', '!=', '') + ->orderBy('id') + ->chunkById(100, function ($configs): void { + foreach ($configs as $config) { + $webhookUrl = (string) $config->webhook_url; + + try { + Crypt::decryptString($webhookUrl); + $encrypted = $webhookUrl; + } catch (DecryptException) { + $encrypted = Crypt::encryptString($webhookUrl); + } + + if ($encrypted !== $webhookUrl) { + DB::table('ptero_alert_configs') + ->where('id', $config->id) + ->update(['webhook_url' => $encrypted]); + } + } + }); + } + + public function down(): void + { + // Intentionally irreversible: rollback must not restore webhook credentials to plaintext. + } +}; diff --git a/tests/Feature/AlertWebhookEncryptionTest.php b/tests/Feature/AlertWebhookEncryptionTest.php new file mode 100644 index 0000000..11a8f5e --- /dev/null +++ b/tests/Feature/AlertWebhookEncryptionTest.php @@ -0,0 +1,49 @@ + $webhookUrl]); + + $stored = DB::table('ptero_alert_configs') + ->where('id', $config->id) + ->value('webhook_url'); + + $this->assertIsString($stored); + $this->assertNotSame($webhookUrl, $stored); + $this->assertStringNotContainsString('storage-secret', $stored); + $this->assertSame($webhookUrl, $config->fresh()->webhook_url); + } + + public function test_migration_encrypts_existing_plaintext_without_double_encryption(): void + { + $webhookUrl = 'https://hooks.example.com/path?token=legacy-secret'; + $configId = DB::table('ptero_alert_configs')->insertGetId([ + 'webhook_url' => $webhookUrl, + ]); + $migration = require dirname(__DIR__, 2) + .'/database/migrations/2026_08_18_000020_encrypt_alert_webhook_url.php'; + + $migration->up(); + $encrypted = DB::table('ptero_alert_configs') + ->where('id', $configId) + ->value('webhook_url'); + $migration->up(); + + $this->assertIsString($encrypted); + $this->assertNotSame($webhookUrl, $encrypted); + $this->assertSame( + $encrypted, + DB::table('ptero_alert_configs')->where('id', $configId)->value('webhook_url') + ); + $this->assertSame($webhookUrl, AlertConfig::findOrFail($configId)->webhook_url); + } +} diff --git a/tests/Unit/AlertServiceTest.php b/tests/Unit/AlertServiceTest.php index ea33d61..914f860 100644 --- a/tests/Unit/AlertServiceTest.php +++ b/tests/Unit/AlertServiceTest.php @@ -4,6 +4,7 @@ use App\Models\User; use Illuminate\Container\Container; +use Illuminate\Encryption\Encrypter; use Illuminate\Events\Dispatcher; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Http\Client\Factory; @@ -44,6 +45,7 @@ private function setFacadeApplication(?object $dispatcher = null): void { $app = new Container; $app->instance('events', $dispatcher ?? new Dispatcher($app)); + $app->instance('encrypter', new Encrypter(str_repeat('a', 32), 'AES-256-CBC')); $app->instance('log', new class { public function emergency(...$arguments): void {} @@ -509,6 +511,41 @@ public function test_alert_with_failed_webhook_records_channels_failed(): void Log::shouldHaveReceived('error')->with('Webhook notification failed', Mockery::any()); } + public function test_public_webhook_passes_pinned_transport_options_to_laravel(): void + { + $capturedOptions = null; + Http::fake(function ($request, array $options) use (&$capturedOptions) { + $capturedOptions = $options; + + return Http::response([], 204); + }); + + $result = $this->invokeSendNotifications( + $this->makeService(), + (object) [ + 'id' => 44, + 'location_id' => 1, + 'location_name' => 'Test', + 'email_notifications' => false, + 'notification_emails' => json_encode([]), + 'webhook_notifications' => true, + 'webhook_url' => 'https://hooks.example.com/test', + ], + ['total_capacity' => ['memory' => 100, 'disk' => 100], 'total_allocated' => ['memory' => 90, 'disk' => 90]], + [['type' => 'warning', 'resource' => 'memory', 'utilization' => 90.0, 'usage_percent' => 90.0, 'threshold' => 80]], + ); + + $this->assertTrue($result); + $this->assertIsArray($capturedOptions); + $this->assertFalse($capturedOptions['allow_redirects']); + $this->assertSame(CURLPROTO_HTTPS, $capturedOptions['curl'][CURLOPT_PROTOCOLS]); + $this->assertSame('', $capturedOptions['curl'][CURLOPT_PROXY]); + $this->assertSame( + ['hooks.example.com:443:93.184.216.34'], + $capturedOptions['curl'][CURLOPT_RESOLVE] + ); + } + public function test_non_public_webhook_is_rejected_before_an_http_request(): void { $dispatcher = $this->bindEventDispatcherMock(); diff --git a/tests/Unit/WebhookEndpointPolicyTest.php b/tests/Unit/WebhookEndpointPolicyTest.php index 0263631..9a4f30a 100644 --- a/tests/Unit/WebhookEndpointPolicyTest.php +++ b/tests/Unit/WebhookEndpointPolicyTest.php @@ -56,10 +56,12 @@ public static function blockedEndpointProvider(): array 'carrier-grade NAT IPv4' => ['https://100.64.0.1/path', ['100.64.0.1']], 'link-local IPv4' => ['https://169.254.169.254/path', ['169.254.169.254']], 'benchmark IPv4' => ['https://198.18.0.1/path', ['198.18.0.1']], + 'deprecated relay IPv4' => ['https://192.88.99.1/path', ['192.88.99.1']], 'loopback IPv6' => ['https://[::1]/path', ['::1']], 'reserved IPv4' => ['https://hooks.example.com/path', ['203.0.113.10']], 'multicast IPv4' => ['https://hooks.example.com/path', ['224.0.0.1']], 'documentation IPv6' => ['https://hooks.example.com/path', ['2001:db8::1']], + 'AS112 IPv6' => ['https://hooks.example.com/path', ['2620:4f:8000::1']], 'multicast IPv6' => ['https://hooks.example.com/path', ['ff00::1']], 'mixed DNS response' => ['https://hooks.example.com/path', ['93.184.216.34', '10.0.0.1']], 'missing DNS response' => ['https://hooks.example.com/path', []], From 488082814f20a9314a5dcb0a47c536a54838ec05 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 06:01:18 +1000 Subject: [PATCH 74/95] test: restrict shared database guard to loopback --- tests/TestDatabaseGuard.php | 26 +++++++++++++++++++++++--- tests/Unit/TestDatabaseGuardTest.php | 23 +++++++++++++++++++++-- tests/bootstrap.php | 26 +++++++++++++++----------- 3 files changed, 59 insertions(+), 16 deletions(-) diff --git a/tests/TestDatabaseGuard.php b/tests/TestDatabaseGuard.php index 76c8b42..f31fad8 100644 --- a/tests/TestDatabaseGuard.php +++ b/tests/TestDatabaseGuard.php @@ -9,14 +9,21 @@ final class TestDatabaseGuard private static bool $cleanupRegistered = false; - public static function claim(string $database, string $connection, string $environment): ?string - { + public static function claim( + string $database, + string $connection, + string $environment, + string $host = '', + ): ?string { if ($environment !== 'testing') { return null; } if ($database === 'paymenter_test') { - return in_array($connection, ['mysql', 'mariadb'], true) ? $database : null; + return in_array($connection, ['mysql', 'mariadb'], true) + && self::isLoopbackHost($host) + ? $database + : null; } if ($connection !== 'sqlite') { @@ -34,6 +41,19 @@ public static function claim(string $database, string $connection, string $envir return self::claimIsolatedSqliteDatabase(); } + private static function isLoopbackHost(string $host): bool + { + $host = strtolower(trim($host, " \t\n\r\0\x0B[]")); + + if ($host === 'localhost' || $host === '::1') { + return true; + } + + $address = filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); + + return is_string($address) && str_starts_with($address, '127.'); + } + private static function claimIsolatedSqliteDatabase(): ?string { $database = 'file:dynamic-pterodactyl-test-'.bin2hex(random_bytes(16)).'?mode=memory&cache=shared'; diff --git a/tests/Unit/TestDatabaseGuardTest.php b/tests/Unit/TestDatabaseGuardTest.php index 1386417..94598fa 100644 --- a/tests/Unit/TestDatabaseGuardTest.php +++ b/tests/Unit/TestDatabaseGuardTest.php @@ -68,8 +68,27 @@ public function test_rejects_empty_database_name_before_application_boot(): void public function test_rejects_paymenter_test_database_outside_testing_environment(): void { - $this->assertNull(TestDatabaseGuard::claim('paymenter_test', 'mysql', 'production')); - $this->assertSame('paymenter_test', TestDatabaseGuard::claim('paymenter_test', 'mariadb', 'testing')); + $this->assertNull(TestDatabaseGuard::claim('paymenter_test', 'mysql', 'production', '127.0.0.1')); + $this->assertSame( + 'paymenter_test', + TestDatabaseGuard::claim('paymenter_test', 'mariadb', 'testing', '127.0.0.1') + ); + } + + public function test_rejects_paymenter_test_database_on_non_loopback_host(): void + { + $this->assertNull(TestDatabaseGuard::claim( + 'paymenter_test', + 'mariadb', + 'testing', + 'database.internal', + )); + $this->assertNull(TestDatabaseGuard::claim( + 'paymenter_test', + 'mariadb', + 'testing', + '127.999.999.999', + )); } public function test_rejects_pre_existing_disposable_database_directory(): void diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 7bba23b..2e631b0 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,41 +1,45 @@ addPsr4( 'Paymenter\\Extensions\\Others\\DynamicPterodactyl\\', - dirname(__DIR__) . '/', + dirname(__DIR__).'/', ); -require __DIR__ . '/TestDatabaseGuard.php'; +require __DIR__.'/TestDatabaseGuard.php'; // dp-13 guard: refuse to boot against a non-test database. $db = getenv('DB_DATABASE') ?: ($_ENV['DB_DATABASE'] ?? ''); $connection = getenv('DB_CONNECTION') ?: ($_ENV['DB_CONNECTION'] ?? ''); +$host = getenv('DB_HOST') ?: ($_ENV['DB_HOST'] ?? ''); $appEnvironment = getenv('APP_ENV') ?: ($_ENV['APP_ENV'] ?? ''); -$claimedDatabase = \Paymenter\Extensions\Others\DynamicPterodactyl\Tests\TestDatabaseGuard::claim( +$claimedDatabase = TestDatabaseGuard::claim( $db, $connection, $appEnvironment, + $host, ); if ($claimedDatabase === null) { fwrite(STDERR, "ABORT: phpunit would run against DB_DATABASE='$db'. " - . "Expected 'paymenter_test', ':memory:', or ':temporary:' for an internally generated standalone SQLite database. " - . "See .sisyphus/notepads/dp-11-authorization-surface-reduction/incidents.md.\n"); + ."Expected a loopback-only 'paymenter_test', ':memory:', or ':temporary:' for an internally generated standalone SQLite database. " + ."See .sisyphus/notepads/dp-11-authorization-surface-reduction/incidents.md.\n"); exit(2); } @@ -44,5 +48,5 @@ $_SERVER['DB_DATABASE'] = $claimedDatabase; } -require __DIR__ . '/TestCase.php'; -require __DIR__ . '/LaravelTestCase.php'; +require __DIR__.'/TestCase.php'; +require __DIR__.'/LaravelTestCase.php'; From f7f0a8c0816ff28c386277798cce9f4aa92e1b36 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 06:01:28 +1000 Subject: [PATCH 75/95] ci: pin refreshed companion checkout --- .github/workflows/cross-repository-integration.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml index 7d1227d..a2c7f54 100644 --- a/.github/workflows/cross-repository-integration.yml +++ b/.github/workflows/cross-repository-integration.yml @@ -35,7 +35,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 78e76934f3f4d8f9688b72e8873565f819d6a374 + ref: 15898c66ef4c67c03befddd898289a6879eddc29 path: paymenter - name: Set up PHP @@ -96,7 +96,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 78e76934f3f4d8f9688b72e8873565f819d6a374 + ref: 15898c66ef4c67c03befddd898289a6879eddc29 path: paymenter - name: Set up PHP @@ -200,7 +200,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 78e76934f3f4d8f9688b72e8873565f819d6a374 + ref: 15898c66ef4c67c03befddd898289a6879eddc29 path: paymenter - name: Set up PHP From b758b4b70da11eea6be6ed9400f84dae8fab0af8 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 06:02:24 +1000 Subject: [PATCH 76/95] docs: align release baseline and source pins --- .../en/content/API Reference/API Reference.md | 24 ++++++------- .../Architecture Overview.md | 36 +++++++++---------- .../en/content/Core Services/Core Services.md | 2 +- .qoder/repowiki/en/content/Deployment.md | 8 ++--- .qoder/repowiki/en/content/Event System.md | 2 +- .qoder/repowiki/en/content/Testing.md | 18 +++++----- .../repowiki/en/meta/repowiki-metadata.json | 2 +- 09-IMPLEMENTATION.md | 6 ++-- AGENTS.md | 2 +- CHANGELOG.md | 2 +- DECISIONS.md | 2 +- README.md | 4 +-- 12 files changed, 54 insertions(+), 54 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index cceacd3..a080827 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -23,12 +23,12 @@ There are no standalone customer availability, pricing, reservation-create, reservation-confirm, or reservation-extend endpoints. Customer quote failures are generic; upstream bodies and internal exception messages are never returned. -[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php) +[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php) **Referenced Files in This Document** -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php) - [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) - [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) - [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) @@ -82,10 +82,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -124,7 +124,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L17-L22) - [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) - [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) @@ -141,7 +141,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L17-L40) - [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) - [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) @@ -151,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L17-L40) ### Endpoints @@ -190,7 +190,7 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L17-L40) - [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing @@ -229,7 +229,7 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L17-L22) - [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) @@ -313,7 +313,7 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L24-L30) - [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) - [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) @@ -343,7 +343,7 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L32-L40) - [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) @@ -378,7 +378,7 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L32-L40) - [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index 5cc0df9..6a269a9 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,23 +2,23 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/DynamicPterodactyl.php) -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/routes/api.php) -- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Services/PterodactylInventoryService.php) -- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Services/ResourceCalculationService.php) -- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Services/ResourceQuoteService.php) -- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Services/ReservationService.php) -- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Services/UpgradeReservationService.php) -- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Services/WebhookEndpointPolicy.php) -- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Models/NodeCapacityPolicy.php) -- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Listeners/CartItemCreatedListener.php) -- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/Listeners/CartItemDeletedListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Services/UpgradeReservationService.php) +- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Services/WebhookEndpointPolicy.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Listeners/CartItemDeletedListener.php) ## Reconciled Architecture This page is the canonical architecture guide for the branch that combines the -live `ResourceCalculationService` work with the Paymenter 1.5.6 reservation, +live `ResourceCalculationService` work with the Paymenter 1.5.7 reservation, upgrade, and lifecycle remediation. The remaining Qoder pages are preserved so their useful operational and historical detail is not lost. When an older page mentions a retired controller, listener, or API shape, this page and the current @@ -136,9 +136,9 @@ in Paymenter core. For implementation-level detail, use these versioned repository guides: -- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/02-SERVICES.md) -- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/03-API.md) -- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/04-EVENTS.md) -- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/09-IMPLEMENTATION.md) -- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/DECISIONS.md) -- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/PROGRESS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index c4be42e..d385cff 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -17,7 +17,7 @@ `SchedulerHealthService`, and the audit/configuration services provide the supporting policies and operator visibility. -[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/02-SERVICES.md) +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/02-SERVICES.md) diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index a9e1101..67d87fc 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -24,10 +24,10 @@ by the cross-repository workflow. Before enabling dynamic stock: 7. Resume deployment synchronization only after the exact commits are reviewed and approved. -The API key migration encrypts the stored credential. Customer errors remain -generic; detailed upstream failures belong only in protected logs. +The API key and alert webhook migrations encrypt stored credentials. Customer +errors remain generic; detailed upstream failures belong only in protected logs. -[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/09-IMPLEMENTATION.md) +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/09-IMPLEMENTATION.md) @@ -174,7 +174,7 @@ Operational requirements: - Scheduler must be running to execute cleanup and alert checks. - Database must support transactions and pessimistic locking. - Network access to the Pterodactyl Panel API must be allowed from the Paymenter host. -- Node payloads must provide an integer `cpu_threads` capacity value; missing, fractional, or malformed node/server capacity fields and incomplete pagination fail closed instead of advertising unverified capacity. Stock Pterodactyl does not expose this node field and uses zero server limits to mean unlimited, while this branch does not yet encrypt/migrate the stored API key. Keep deployment paused until PR #22 is fully rebased so its `NodeCapacityPolicy`, zero-as-unlimited rejection, and API-key encryption migration are all retained alongside every PR #23 safety and Wiki change. A partial CPU-only cherry-pick is not deployable. +- CPU capacity comes from a configured local `NodeCapacityPolicy`; stock Pterodactyl does not expose a `cpu_threads` node field. Missing, fractional, malformed, zero-as-unlimited, or incomplete inventory data fails closed instead of advertising unverified capacity. The Pterodactyl API key and alert webhook URLs are encrypted at rest. Keep deployment paused until the exact reviewed extension successor and Paymenter companion are merged and every current deployment gate above is satisfied. **Section sources** - [DynamicPterodactyl.php:48-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/DynamicPterodactyl.php#L48-L75) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index 665cac9..8928c7f 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -15,7 +15,7 @@ companion lifecycle. The reconciled extension does not register cleanup, reconciliation, capacity alerts, and scheduler-lag checks are registered from `DynamicPterodactyl::boot()`. -[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/04-EVENTS.md) +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/04-EVENTS.md) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 0da8aed..05ce2f1 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -14,14 +14,14 @@ process-private named-memory database and rejects inherited generated URIs in child processes. MySQL/MariaDB tests may use only the explicitly named `paymenter_test` database while `APP_ENV=testing`. -[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php) and -[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/TestDatabaseGuard.php) +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/TestDatabaseGuard.php) **Referenced Files in This Document** - [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) -- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php) - [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) - [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) - [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) @@ -86,7 +86,7 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) - [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) @@ -97,7 +97,7 @@ U --> AC **Section sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) @@ -142,7 +142,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -361,7 +361,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) @@ -383,7 +383,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -425,7 +425,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cb677ddb5f7e5f961128425b06c54b598eb79e3c/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 0bc3e97..db7f1db 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted:qkTEybd9tQzuDstX5IzR1CXs/trJv2Qp8kaORmGdEsjOxLytJAqUuHjP06XJn9y+iXOi9CHh5MccEBo3czEUCbEI3xi3jI2FX0U5Hb1shR6LDZa4SKyGHNVixTBNySA00Nc7Lz+raBGyJ9EnF9lGDKWB1J0M+K73LX1rF7N3R69cErBcAhuvCBd69rsyUTTKSXgEpXu6a6WBUCYLToWdn12p9VWVvjTtcSe6lRUrzgs90/zIfQVq9RYyW/9LbF/T1JjqYM0NGvS+uZhPFi3p2U9QVLIuGWoSFWeMUW7i/mctoN1NLGsU3TIOSauX990uB8YSEC+j3CLEU0RFn/c5OsWoAXtfngYrjb4AGHl2NEDSkwlciQRkxkMYxFEZyYcHT8Gpy9mvFvx8bbUg0Pz6UsIgth+Wt8ksCwhqUfDKRSDFIXTTfvORPKTzfkyLwlHIqFcgDPVkG6zJI8I05IjUlXG5jKJQFuSvTIn3yJqmp7ZhvKQoeYLzB31v5M+ZOkDLxB20IFzyEJJaajhK2ne42xddTRga+uACLExPlaXQ2RJgP7aEh4BxFflfEZTJ34EAFDODWNpg+cS/h15EWTsUaCG4uC1kiMBrOd2ozslPb/B4Edh29LEeX6942jquAGPtDbui9o80AA5R7YrXIWL0yCvKlGIvVQkiQRQKUdaVYNvT3BlqJ9Ka2WMvnXeD93o7uFgQDqkb92et5LlCLAyZL2hhn/HVQ2au4V4WnXgjVYGwqLpihYFplV2o6Ul5PDnwJGD69mAO7aSGG4TBaz1vo7thcxfYaEN8buhL/QRsNVzwqTeN25dxKdYd+zBxU36BMRYfjftV5aUHpmuuyJJkM5VRKQ6BjVw6woeWtQG8FgIoVUuFHpxorMTccI2C1mpkmzgRNMXQ85uoPlKkLHfbtEhYmKBBI5pISQM9VE6ya4qmYS3ZcA4Gby+GuS+2myO7b+pIgX6Gq8Edw5WSPn2Ei//99pnHyVX5UPawG98jbNRlrQs2TtcrBTUT98D4BYcMA+ktxGDZix3F4RcLx5/elIhe124f8f7S+X8phIq7uGTw+ZxP8gQsdLdGaOoF3tin+ZOK0iHk3oIa+E7zaPMUeNmQcixZRtKa4oIeo6dr4zHVltAOiLtV52OQDsPPCU8HwUO9GFXeTYlUMXhErji/Bg7K2iw712B/4pQW0+0M4atRKpXUCf0AstnGoCz8LlV+hEsMY8AS+k7jCk4TW4pv758c4geH+8hGXMLUSEdVybYs2P4Vk4c8nAaIEP6jWukiDhIps/dyb8RExWg5BKcfGJZXTWi3TBQKnGIqc1JgXXJUAOfGwP87PHb9WxxWsvl+13KF6/JUV2RuX8NWSAmST2z9I5whzQnfem7CCc2i5yO6yqpJbPOt+hpYlqFYp/yd6gkodn84E4+o9G2F9NamhIk1rCcqX0YoYhYX3he3rU49QIUaNev/DsEKQc3s+K3yH3L969uk8nvcFIDEREP3Ke/07RicsySihmrgxJ98Ld4lr2V25uD69/exLybGUdn2dDcVBUfI6jWrwipyYCInTV+f2WDOy/ki/Kv/G4WbDZhIXn006l1s0GcFML1GXUTxXmJY0ku4dOxbpkSooJ7fw4n3y6hHWfG8HpJT6bxgFd00CbYoe/b0gzXvAaWW8vpkN1sYSWr1kqeYKUzdSIW57T/K/LOKTHdgZA+L0R1R8CEvL/ecL3GkHaFg+gEYwMpDWhf5rCtDxKebVIATR9aw07hbWczXdZwkDXJlVd5V5vdgORzxjfzO/OFC44ruOlxQSlTZLyulYQFp9dHxHnHSP0L24zQXaZKtefy8cnmOapkooReZ+wZRWiAb7fxmo9D1teGxlOU66NKDFzhuXbd+HpEiPqGRF9y08wPLPou9goHOa/JMQmjgWBUVuQuDbR+a74MSWaZCcIwojBJ/uBzCR1IFP2H+BJDuKSrdeLDMuW5EJu5KRZ0B7R+zFnwOxiZ9EYJTIFO4DXNRb9ZL4JZaZJDqwUUgBM8pWHec/4cM+iRi7hh+rkEMQRAMyGpem2L+oSpr2mWWzpe8wQhlaZeVV2sbybXQ/c1TEtK34eA4FlFqimXo12UKrmimZi1mkAyuF98LXH1wCLNXeJVLWZOMKrSl17JGy+Rgsx9dEnAmdAOt/ePsBXXphzaiSY+6GMqmtIINfcgpsvFLf7VhdP0yeZ+kkaT7kJ6yYu+EvJqw32jYBjw3cBy03f0wLMX/dMHo6VPVsef8AiKqBBoTxb2uWBbY31nXY9EQgRoYajhQYdmKkqEJWTkgXQTwQDHnUdrR69KAqK1wYfDX38GDERT9ibC6fXsUZGq+QgGm8VZHTsFTnVWZUi9EUCA1oH4p8NtjCRKQE1dUmCiF/sMRKwCgiHZ+WmKV4ixhHV51T5RAHQ1fkcqc+hPFcd9uEqHPrwvlORQ9jh5rDbFRNCijsw17TiHm3NlZIZ6TOhCPiPO7135f1/4QfMvhj8NftvFreT17bU7G6ZhUQAvh6EcXhWZ2LDqZR6Buji6hu1u+6WgCFFNo+TSLl+h0xhKxqKlA0H4FQImLcJdXn4MBTrmQhqMe5H1iyxIN8bhT42s42eS/2IJqrvjiLVVNiU9DbRlYBe5TsLfZuC9GQsWYHdHB2KAAAceRlYBlwnnnVPexQl67P/G9sMfPJkJP7aduEQc+ikG8og1weDdx5GYauM8O/D1cxi8/7lTsEtDIGXuCC5OOHBs7utoXRrzgtS/D2kgNytqDqSaHVKaNy8NDlNMYbjHbsr4ffxNCRN6Pv2NPi1RODmwAvliw6D7KLOfoqACJKyBasvMnWyR24InlREQefIeRrWJ37pr9Vq55Q3FhvhZAc8rPO+f3plstLlPFQuqz9RWznCe1tPE0niOz5NHBZI9lhIv8cOJgZRzQJnMNAIPVderB7zfqLtTAiq8aipiVreV2y2vrLz0b9lyC8yWPsQK3aseiv9yw6i9ehl4z/sHroeApfLHdyEscUVNJXOvapP2qTfZ9jk4hocuqydv/duI2D65jyGlk6QuIPkjjMcJ8zaFur7eFq177IRSKIy0XT5XPXjUFSsnXp0ChOnfbgKyNvD71SvzQT7GwZI6hAH67jxNZKymIWPsLwAFOl+M5XOs8X9EnYbxKTReoFUvgerc0IprGMeJ16tH14Yd0i/HHak13ShbBkqSOrBhhWBRCCGt73qsgdMPKqQaZAihM6hzVtV0uacQePDcxX005Zjorr5rGsmt6BTBWli/TnwDZB3Ttch1RUd2LJTCCIf05zCDZAtrx3zbm5Zoti5VWjScQta3sIvXlpHyQkCjB2varsGqAsAM6xbX6bHqsYlZCwlk1uP/VKVdUU65hWydtK0mJCHJsMV/H8ph35q74Pd6y7yvcwg6oKZCuQCA+Cd9TiyAc3Nt+wXdMFlMxobEz1J0fL8o1BKpsKI1yNn3xff0/UITO4WG/FJ3ryJ1ROrErGmcxjYSgvBsYrkhIUJRMx67aSnqHC3oQ7SWeFeJrTuyyrHD99crFg1wWW/Ny7Jkko38NzNnHHArluH3t678lUA+iwYkFUmGoEtS4GEav6aW5hU2cvXiL3Sgog1Eht3LcHBLRR5Bf6n1QOINMP3Japm34G7BaoZ5TNwpgoVoJL4/vUu1ncx7WYfgP8KlUhUAWtI6NFt/vMxjZ9vhCM4Pgn6dQLn/vpc6aYRsyEZChXu0wLqM9O9zLbAQ8qEOA0e42gpKoXjDUYBnNFu0Z5xjiaRu4B0LT64hpm/n8NvjzD3dL/9wv6xCTKdt6T7PmeIUrpxi1OcprTww1m+Op0qyeOzKRfWHQl9S3dREaZ4AXqDFETvCYFD/VJ3U5pXRr93uIH89E9eoGaZQbr31j5m5aYERY2ZXF99fhxPSyd4rranhUy7m67NgGGaNgdqnH/9rR1NPpFb1xUwymj4NoSg+innBL7DfFKsWMHumXC3b+C5jvg3WudMgI0+ODGO6MoYDiERrxIidOP5q8ZN4Jfts8pGffE5/sd8zNMP36qD4t8nF/pskZsgdOVcsUzPmuB86IFlV9bD4eC/RdmJS/lHgmgQ4eTpFRNADPwqz9vkoPtQurxMYLqnrF7LElAIGXC0U6k/oyDz7SKDz27N5B7ryjSs0IVLV2Gy7ZncOKbEyj9CPNXy9vR8rAIDrFLa1QNw+FwYgPu+RoyTDJ9S55NDjpALze3Si28hXfGIoA0HSvM4+r1S8EfRrQmWs1o+qBh1pDKt9hnFpqLjq08Kz/UarsuU/dKAxkzP6FSPHWRYY3YCd6U4lJq9LL12d9FcrgYIz72opWVgWq5BNezdmM5foqsAFgDujPmGbB6YdL7kTyt0rcxMBkjlP56SnD8hLaBG7oTkf4GCzquMcMhaFf1pklIKJi90kufl9CDN0eYHjnF+AzeLf1p/Ruq0IehmliQXA1No4mXjiA2qU1BnmzqTNCyAWN32S+fAkeEfSd+AdD4sMJSSLUhNwaoTQr3qSp9Q0qW2KZGchDCBDXE4mTCyxPNDnHCSvmq+ayDviJacujoKbZNnuuZjgJ5eitj0nuD0S7jD/URAoUq8UAEzo1qq5eziSUw6z38U0v97ZaU0hohyYSgjBAv+umzJOrnY+Wu7SVW/53kYb8GpMhwkgdvQRKZcBEUuR8o2LmYWilmZpKyH08poYLj41wtsUQaVqhgItvECi6G1V1MRg9BzvvHSGxU3jglpZUgzv4dhYrUxabLiVdFRLyAtZ+nx5YSidIxtStPEnWKIR27k0BIsYLP0yO7npcBkx9v7urwM1oh8q6o9mtPT140KgBqUPMRKujN1Qiw0kQ1BM6TddIsUWMS4Jr6oH//jZqDqOM1BgFjEzXhdWWTnwHe8Y1x35EGBfYupFepa8/H/6iB8HUnbLcEg0sS1Hla0OHtaut4N6i/rJNlfBAYjK1tyDv/cwm/bEClj0JzLRWKjf1Ae/1b0LYWIDReal8V5YqrdkB766d1yx+xZ+oU0c2wAn4ij+Do6RRtrV4lTFGs/PNS9CpiYS9yt6xXt+2rFuKuWrDxwLl5krZDJKTvpO0s9aF7jjljsDfcaKJQQTlTkL0h1z/KZxm41bg+KcbsyptkUR/8Xti/fBFOUSBOUd2E0ppEA8/r2pxLlIYaIQb4dYsI3bqvONiFviW9qExQQZ2RYJ9dLDykZiujhQ2nEJQOaCc7e+NViygsPHE0NTb24LIPbnAQX1W1PCt8RtndICZAJI60dVMni+ctjifd/hwY0Llgl7d866veLh6q/YZn2f2qBr6ms+ar6mIrT0zapYhNG+hLWaXxThodnNG02y4Ifd9wFSEkMOqaeMXxCBRquJ8QoH9wSd6nYO3VDChhkPpqdATuWj5/hI5SUtcmDOKTe9FtpP+sSIII8thsMraMi34XovbHYPFdAwrSy7P46GbtrZKTG4gKr3ZtlGIMFlYEPeTPL322mNwjrj92Xtiv99blZVyVShhhNHlHvcFPjXvVWiI3iNMcdDs6Q4ZRSjkLTxVaZcFHL7S6/fj/TeKcISQMVvW/+80GI7791wFpgzGt2UfMHcCakrxgxpldcwlqSTVsMDRMkWaQQzsqaODqL9IZoMYyGJweawPyIFbCanAUfBpoJJUHrPCPVTzsG+5TupSkaxAqSmonKiCcqUA4Ra7rc7B6H67hFyaqzDcQ0HnObKpJp9Z47+70k1bqqE5DzVn9jE/pXNBplDGe2EN1ElmWGZ7ZFl5RSZeNxhCZ90+qOFe0RfYZyk0g7qi0KDnSmIttTqBNXzyktDJhs8cqPvs17y38gAjI9Q2RtR4ShU++7m/id9sSjv3xAHhawuUdS9Pgj+OO554Xezol7Wdn0kx+oTnVEZsOUDtV+8dx9M1X+b3yhEONQZQnpkLzz5trviuVmzgLKxgopFB/Hmh1d+E4KOHkV/SLfy+a1bz2FXqUzu9fX+oRKLKmJJD5Y4sp+/gJSH68oriVKGq+hvF4F/RBmkKMXwE8KTw1LUFl7dMvkMuAKoNnklEyyyVdKit0vtj00CqZhG660jA+5z41hadJqUZ+lK+ITqJjvUrjmKOzQ0q/CIIJETrpCfkjXZmqb4Ebz47DJ16umz/a0IWN/tiFyuwoxzvdGEMGKQ7o8Pd8BciB3LBnFUoHMtR0yW0jxctOzrftPZ/vh0JSHOp6ux72Vh9AZgi5TphCRvcpKlba/I0IyYzkevNboCRgYQP+Ap5rj+93nXiGWTfRk2mSpyLral3GHzhAMgl972OIpcT5/Jm3DX9Rt5xScquys2wJ2dVY8lhiPPr8zMvy0frQL7I5056M0eQjoInwws4fIZtBfEYy+ycrVnZDK6EIc1FdGItERZL7gIhphZ4dcYXtj8cRF6l2PlQ504mB2w/WVH6zE9naxlibeNF1JpvRZ5pKl2Jna35M+axy4dgC7rhji2OIE6pjCle8ZW5yezeopFZ+gelvlQrNqVR8pA6lGoPp/VixuWxbDG0MqAYPN+4+UqdXGvEF5VGcjWCJwfE31XaLZNL1XKfqzBuEAD6R6SuRb4ik9jhKDmCOvYyF2y2jxovEJKGv2qQ04poITEbD9Z/VoGI6qH+Ldfx/pHSxxYj8QfadppQBhfWROJ4HaW65WXESK7kQnLKzIcRk97zLXiBUAfDnoROqbd+VzlfnXGEogSfskcNcyn40WdRAZ9EkO3qWeT8L7eGa70tx0EDmSfkv4EUZhKMKbJwsAyedmc/tmVQyk2CVQCzgBMW5AdHgfkaHRTqiPuRpkSnVVCfi5yUcfdgKeU5eho1iFzrBJ5FWc4LtiU88uOOFewUSqski12Z7xAZDF9QH4eDOcWEIRwy8nzflI0C18Hjz/AVBfeKxfuVf56MJD1M9b5ZyKgXF2uv+2rtOC87aqaGDKkmG36eWMjUpj55xm0OrxhnFYb4io1c7Ar9GHOTCp5d9T8b8AlmDghYu9Q4BS9eu1fC5mk2qntj0gbtITw9yrm94mnFR3epFBM5VimXsIKyfkN6vaxi/VYxLzs/m8P2/iMz5YhDPSpEoE6dtGi+RYFQoGfmf4Kp51MvhxKpBWzIKUZ4oVo3bSR/xTtA8g7m2Cu9TmGyGzoRsGZVWPwenitAOr8BK1F2gZIetevGghmmjb+dsTllfsZSkAVO+a/QWVxiylobFRc/EGg1uQzlL5YM9+6L/vwXg6zBN9kGoGj7BzOCNk1aNyPkub8+YZrb16Nj9GZcHqGJWRlAqG/XekCaEDdi/tUuwHPCTvJpmceD04ErapLgvVI42e6zgSXMnb4xQ8znJCFT/H85Air3ZAMw36GLTdxZbw+csNjB7990zjLDB1/gslSZrLuBFvtO2ciWE7AqYJd4YUlhLF4iLpy5W4Sw50GjAW444Fgp6oVJnQlL0tV8APr2xbLWp9Eo40IOgvMNVPwLP/v39jsXjKT+VrFgPBaEYyxNIKtx8MAUPhCaPKzpEL58BAo4j14o00Ma4zDTGbFWPXFfbTMBZtDjBD7n6z/GJZUFz61giQOlLsQ0APQW//bMxmh8FgqEujhae7IEDDgm98plwNfmKQKAv+nZB6h9iie1nTVLTm5P4ZSw+v3VpETskl9Bq8RT65DPNdkO8pqMBj8J6Xm51FlrR0ErRv/ynI11twA390S1F5cLg+OLAOx271Of6n2wxWTJG/peXEcAVfFaXXlsmvARiKku8WQu3W/38Uulrk1fg3setfivWSWv2nJvb6NLQyqX1aN5B4vMtm3Sx4oi+QCmHpKr4+n92EdLsHfZJa4Ldm49Lqk6CkD6kncpzbtAjIRTVUXcC/P5ujAwgZPyCyhiwkRJnc1ZBJmbF8JianRsBqhnzXpUBlsOObVOdyjLn3rFDaigXy90uf3vyrSJP1LBqN6DjEKFm3qQXpgmEIqfjLN1upGeb3/PrJV6ylEFwbsPv03ZZvlHP6RLo2fOotcZBh/E+EVPvXv5bzjYVWfDbV3wf6qnr5ZX0muxzBkYOnVp2m0mDA5cgkhI8pY8vXhQvMRBPQpqe3OPJmr1HySivFsIWnHbpSKfTYY9BJYLlEP7cQWwboEHAeXdMpmTx1IOUnJAO59nOml+xyOCSwelJo2W/nCTPuEEGkBHLjpogzvEBe7DZ8j4CjYynzKdd8UEVuXCkKvQhDC6HGQhd56b1uxmxh+Aq/w07/nYu1Y60vEk0Mbi2s0Jo5PpcOcG3ZmRXGJf+1csDOpm4wCi+iF84wBewgxdIegpjPTRopBHEPYH1MSRHiBliqdxf9gipweLAX6yLOk/N7H/gqXarYkCdZXxEjpoZauMfawkM7Q/wSjTKV/vi0en76dmnTHOQzAUjGfBEdm3DtJRZd9XNP27syr6nu2mefGeB+q9sHnNOIMkn8+ZBd5aQdVZT/HvT52vWseAb7488OnqKWAXinkPMoOpx151M5Dwh4n5aMVSqD8+cwTnrSlcuBO+tFrxdDhpCjOY4HRq3Bipo8A88g5OJPBxTCX4Ms9FSH21e/YFA14rMyjYfBMSz3rCdSYp1Ni/U4JT4mU5wGxE0/4djSDcJVd69oE4XKftnVrZQuxz1xKObEy3VSf0/4VN+GtRu9PClRTv63n1vWX4R52q3ibpWD1gSnCxUnMGcovNWSM3+syP8G5yZFHgH8sVuthC1LvODHAa1r1w1gzLAWMMQlYzXo0CRruV6bNDGlcp6KZkgbmOZDX1DWXkrz0r1sTmjTSM13SBuBW4EaNJFyvoV5LLW/yNcUDzhhwysPeGF5df01d+svZEAgHYA8Ogf2b0U7Twj3zx8IqyFfuk+q8TA4trDvU5z/fDNnZazo5r526djNB9+vNMRuxziw0qf7cZuJVMHR5+ek9t5JprtGyXisj7a0LNadiSdFxx5hyMW1SStaM64Aj5w9+m1wGu8Mx5eZ4YX6tXpnc6II3+8SQY20Ui9W8niZVOpr4ybqsaaHVGW9Qzxm6UJwSjtgOcWVb6RsO3i6ymooRxQbpZv39tLrxc42g4Vn8hb6x1i3ukKrvtMUvidfbdR15kWYyV1O5PcPXZ3UnMI5fJS8NhsFLE60UNzIga7p36e4W3b+hKghoKnk6JfRtSn7W2dtJgD+pJPhKOxuOLv+fLBT5FwIOHtDzSrdfQrIeiw1FAOmemg6VLbIGiZY86LzBOGzget0EKnLBmMEZip7FK9xIPno1ek3h+EQhg+aDtm//h/VR8Zaz5H2ls6UThDjbVVBw6ffW3Nl71KdgGDk+/D1pvVIc6yfpAgfqt2IYSIjiwJAlvqWZWxR/DkZQUfO0Tjx7fbWp7dssuOrIwo3KQALWFLOBCEljuas4Sw15z2kEQgwquReMhCByUT8vADZMeN1VzAt6X73/ZByCwoVx5rxFjuZkfpXOoxeSCBJtTBCbDlmKHAEb35Fo1yDcQDSk5TlcgrFG12VRpLkHOlZ+fCRn/T49V+TRF0MPlTh2yuJaAl0K93cs1uqqRATX0KsF7XdQOU9FMx8gr7YrImpvgUCheB5XJR1viAxxKCQpaAPpG8SyM1eAbTsNmWsDXz0o9b1h+iz0Pndozebu4NtJLqSXpXCVSsfLlbAaCdHvQ/hb7BEGKf63aL27oNfROm8x35ul6mLX3JWheWr1oPh/KwLgJhOlMPUEDTDMzSp9XpJksZuB4ricLei7rRIn5YE/NWaiswBb5oknS4hicl8YYYRzryUqOdC/7z3GTLXpmFP9eSolf8/Rzt5KNtJQWQK8SoiAbu4e4/ScgM1wzUaNnMNQ0RV4wFAwZ4vvkFNDzVAwpJqWIPaA/MF2cGJOfxA11Ssuxd/2gHXF65fJ1y1sOi10yNWjdnZjjnf8KEdd8ApKjNpMzD2WayEQXzmXXKQ5Ym9FlJb1oIsSJt9Fv2YauH0FlsSO0IWOu7iMPJ/Z0mo5ka31AtBJh9c1gtUxm2xo3t1qhMGnopFozQqeZgiSufSQ3pgrGrUqjwzCsmRZ4qtSOaCu1eDSgR2+DTJ3kSjU9IkiII0G0vFvR0bwL7nOFWBHzs8LT6eQic/CCMCJXuxvvwTknfgrDYIj29BMK5Q/PoMO7JMlG4mfMQ/65QkdmKvVVdmJYl8d6kHjawEtS0JsTwaPFhwNQcXXR4QBFtfZq7hZTyAl0VJ641n3FdiK8YjUJRhRVErBbY8vpSW8Cw5DXTo6rVtbmDM3GHhGWL/EQmL4yVLnmqJloHiCH9lgCZ2spd6WdTbg/G8lS81eFiE3AdnUvL8nOxCVE1cm886d2z5rJL7xXOBfhXiU535UD1FTXOt9IJAGFOrz3q7a7QBcN0mXqjabPSLUzao7SLxzzQ3N5BBtY9E5A6F/JOeJ8k1azGBsbBmHX3gX009gjdyh2FEi4isGWUYmq/ppVDOKRM9TrYBIusyuL1uJnvliLE41KvUnj9cVSGu6Y+LhOShU0oIZzNqlLz1drq9WtJ0pNOBHHcDBUZIHKWkvQu2Kj08LAVuKoqCUTB+bbFSubHE8+P+LqHhU1Efi+bofZdd8IImHxlzSay2TwOJmYr/vg1ttPsxY6QK2cUYrisuDe9flpa6aZ1TDUghwOD3SrGayV0EtJznsqVdhFFrMhyJVUZNqnu/Dacu5QExvHCzFWycNKt5DhsDafNS4OhLlgZofPhh0ORCnb31pkhnfZH2ViomqngfDk3HZYuwW4eKaQuzAskCW9lIk+PGnnNa4MgKye2sy+Bth5Eyn2Y0CHD3wtChNaro+GGoZpaiOyv5qbJLbMO1FfBeD7EGb4VXFQF4VBxnnGV1OFZwDKoa7w7L//On/9Nq4eFY8IJABXL/JWxphpALlAImWxSgoAg837PbDY9dbowRSrVQjhJZUM09BEL2FR+P3kwPwmzE3ReioFgvcAZtTcjzFZs2UHJSk6Mcphkd6ZCr5HIcqgC6GXPa4Aqesw89Uxz9DZfpR7PJkygyZQzn+nGFe9UDOfyqfNF4MxitwhtdniTtmpFTc2JmTNNGNe7IOzYE9kwB52RtLgi79orjTDW5DZ5TnJIqM3sbis0VBgUGXb5JY7oVpXPDmp5XByCkb2voab6P4uFhT8C7FmtsJVQyPRlddFGilUPX+V+n+ANkBMUhuMdowRyKwSxfaNsDVSgdTuGpOw0N2qr8kDOM3NDaCSUXNLoaxxW0NPdO7C7gFI4vcdYhiHy5lLmxuJD62giIjMqQOxH5cefdO8+eiMemWEBA8NQ83eQD+SCHuzLgo7LoIvZmzskylMbYFIwEIzAcy99HjGicmpxKzHFHyN+CRurnuNxaaMqx6/iNmvXjrftA21yI9Yq9T3Yip/33ksWdy3c7IGe+PI0WYExvJ9c/lBmMd6SGu8mKYF/pMxVOATbR5+xtU9EPvTKfOM7TmG9K0faNj7RxdZdua6eui6PekC3iqcWyGt3EGe5j/do2IYobTVDKKhnMZnSgEOmx1rTBo2KKbY4mYB+RtNvMhRJW4StmcRz8tPcGwZbrgTCjL+D6d5oxRiiZo29zSKfQ/yxmLwBPZi4v6LgZGpCMGcUqSSH96k7eBtSoifW31yPc40wPMNsgRBozhjEagoHnrFGA8uxx1turvhD+04CaMdCQGjZ6icqM9PZrL+N0vjxFN7feMPCHySBixzE/k0gwDf7hpMwZnkWoBwF16bK8pNYxmME9DrFDMG1ZVELOxH1PqMzOqDTB0uv/9si0Y/5PfxIk1H0BbpxVOacW9gDfuwaxVnRYlTl6JDYgDqDuXSAokO8ldVhABFE5RQdKb1J4nx2I7VDmS811kQTLZlZZ6jdvLDKKVq/yvnk4j2rXW6cC1j8cJ140GxQXkK1EYNUV80o8Zix7dY7gJMoKBsCA9hXFD9nexFfhUNHwcjYNhR20syWFFJehOjNJIcRPibYc15Zz5AqnBLYgnqo78xogpUJYMsClJ4ZMBWfGSuoWWio9OqVU3LHKfcvBEU6TD3xWTr225Cw6UVNB8c2OqwIA7Q6a+t/mvH1EKysRXxsk8iOTZ6b0PM66iEtEt9tDBAPzCWrAY4c0tCHRFXyq1UuK7lRWVaEnrNlpoFW08Q3zpt1nUR/chEBfQNOITrI8/imqT+CMvM+0hhtK6aokFYHxdOXeFRDOoGeH0/qfVCAnxv/XLz3ZS1+qeivmj6QmjR+3sKYPAMRv9H+YzvZ+ujz2VW59RyMTJaZswXzBmdwYfL8dSxo7tgxp1B0kJiKMfPaTWty3zszKcCc72NXo+hhErdqfA03QPD/w0kYChY+rX321xwuVFltMhDKwG/b4N9mDi5be+8lpEMlQsguMMFUPwJRtiHK+COc2fvo9hujDwtxhvv9KHE3rouXBsqhqVzezXbnSCJRRQg++FNw0pApZIaiBJsa/oIG5PtnyPFCNSfIo9ua1/gp2lt+Y5ipU8AXJTf2RbmbykJqlGUUo45aqA3kHtH++PNVDlbJAwX29qRziiS1OtvUQw4ld30U5+phiaaVP/Zq9GOs0KT0bernuZcmtau2dv27jESU3l4ipL6yaBpqzRfwWluAJhVizirM9O6Ao87LEahalzvTjnml95d+SCjmf0G7HMSGPY3KMiZUoyeOZ94XSMYssRKNnkx3mzxJjPuH7NCW/x0HsUxFLsnDYBl0xtYGKYpIAJoMIzCndZaD3FtRj9AwzhDNe0bsI/BwQ3GizTyr1TGCdXKCy+NaIB+5/E5vfp+1Atqey0P8Ak7ehDSNvs0NwAItMjNWrnKEIBVg7VYs73s8nuf2rXF4uZAbXAoSuljxhpe63JM7roasaBHvCA11M2/rw+vvLgBuLUjdGSbjz245MQBTwuruVCg27RyNT8kyCtDzqJeXC5z1WSLGUUxmd2YN9tJ6/Iasx44EILMV6qJbkfJq2VmcKO/w40/KM8VqOHuZLTQIf8jGWgn6bwgady20kUobrKVMR5/vX2CH8yBxBXtjCmfPede3G74VSjUB3afEelgGPcDQlLia1r0M1Fh9eMQUyQm1zUht6iHGBBfhA0wh3fF2wRVDrMDe0+0nNqknX3VT1GrKm3sZ83xTirO5NNmKXt1SCvF9hpueC718ZnJvfF8o0n29mep33pAy62WtTkR+aMcBEsaDNGqbXfXB6SSg6eDcpc0AaUkawDlnnbPOm3/HVPjpNVngtEy94+cVBDJ9c8ceeBVGj6gcKE2RZYKRLAzxGshUKstkT4aO8i28lAH2rPazurAlVOuVkcJOfXKMMREeoU468NNBQti1Iom7il+PAxKMgRmvgJ24aV+5kSOm6oFyATQE/RAhp1TXP2jWfDhgGlXptbU+Qf11TTOCKYfTmiSVBSwwLZuCxUhEH9NxVCWBHi+OTeuecoa+L6Ma+AZhfFwi9sKOOUsQG0BT9ZApCeg6o4m0XhqXu34iYHlNxowbrnkXKrN7mPzilOALDqGnJSX4hLsSHKT4INypfPH9qanWiFAqnmJ3/E968Jk5ZSa7hRbm4OUL1W0tpfYlsHDeVnANkwLsWBd3PLIe48S/qhzNzmDgFF1Py8fHc5Jp769j2WlTgoponm/1y0YsyBI/ywxaIy1y6fVjKqJC5HqQVjkLs+SrwIFDFUEQ1dzTAbhd5+rEtvz+jgpTGvFpE/7FHohc3iRLx8F6CcVXffFFDZmRcs0VPqmOyJwdVd0x0NECEoTHBvYqrpV3+j+RAkibPFt+7ultMeBxwZY0NQ47GJafHRAg6Y+RiOw2pPUqVRjeiP9lUuAJfH5ACz7iFZ1cIr4zMt9ZSdrdb7kjw/D3JBtVPk95Y4J/iMef6MFf/qMmbf3JhC16y6BnOr0T7rw66NlaD4zpR8jIOHFErzAhJltsxcHmcHA9GoAEAjq76dHMQ6XrJfC5zKlwLLlmndHniu1CKDCQ4PXqqhMn8Fi37/tMV9fhJ3OXliNa3ZV9gBDYZ9M9MYwGE/j5cIK/tpIK1PFdhX6rI9e+MS2rjVuWh5/2vFVrI3WvzFuOVNywdB4JC137UEqxYIaZW7Q1MI/ZrhkLuAN1UUBaEzFopW4Mc3MTK2uSmTa4a8rinCM2ZbWCQQjgGgyhkN0bnrXlVtHeznx/HTGFQQtArTVtVygtTg6+GpvDEQgl2PM4eU0GOe8NuyTPROjOGNh96apt3l+9Egxu6JEY8yl0Wq97Y2GDmk16/Ki0SH/OwA34vSHFxsdFHUkHWHuAqI9V0JL8yZoNW0YASL+w26rbf2Ldm5GHq8XKyIyPoDeLpdgGT32Mf1XqKOFlj/DBbCfQx5ZFC/ifuclNbJa4nGorT/zaiFNoj1AZWBAzik56ysnfp3dGj6XEfJfcftQ+jEeXXwyAPD7XvVI/uXQ7rdKW+ZC3lzKQMvVCQDCn3QRKfQADXkXNFK66y/RLZiPg9aFBKLA/9dDIBa1mLsRgk0pQyqCCfrrL5Tur0eKPM/JFAg5wqYtpHl0wc2zAul8hDfIQI8UEFaDaySgOcSmD9hVJ1d9Ju6Q6Jlu8xwvorK/UeYQDjZ/vkzzzxbvJxILXsLqcnInl7WTswak5kRwvmg8BKKkxo8YQvTp9c1bIwtH3aKLSKTAYDNqSQPv3YZVthoOxfNs3EQRJn9VKa0uZ19E2nHl5FnbrUzl3thPnl662rhNbKBRRWfrOuiLwKx0MzsCdqIoQNhJcFjUZh5KRjWzRVPeIdoiTc4un9yzjbcFu1/bdt7Dd7q4vp9CJlYb8kFHY0KZH2/AF7LLGUYLuL68uh4kKdbw3k83zMwQO3MFRiV4cm7uCNsz0JZmFmYh/+uk0ZFY7CMX+ZkAEpoiT3tLGOVr9ILS8n1dowYK0+PF6t+QWBICSrvkjYRTPEKrQIEsmUVX893EvbQfSMX1h2W7U1XXwcbP6rV1pWhPtmoX6HfKREigcgRvf3EeUOQ0pOMQhVo+lXmhRkcHqsDVF5J6bf0xZ0QTgDEEznQVb/7TUWuhUzTH+yPme9yKYzu7NWPwyoTXA8aNlcxuXLiGHytrfxS5tjcdj2YpmWed2a/uoHeTyBrIMwnwNE/39vsEeOK4CFmdRXoFimwIBhyRJ1QZtdxBimAwCq1xkfF+zZuEOgCsHZRBFP+0gvHBHJg29HoM0/A3p8RrucfFXzylTzr26zUFmUezCi1kIHF/3se+SjhV1D2lhHdVp4hAY9O6AeBFBmwfWByV2vr23g3UJBB22YqKoJG6tA+2QHax2IXY4c7CHdzxVdUZCXUlEGJsxOuhU8NgLEvk//U0+AkflbRxxTFHQnMRnXAJouv81utGIYGIkHdCIz7eSVJMV+YWLsFU76A23y6d7u2L+zvd8Tb3kxYaA35U9kNZbbd4NeGHR6rCnYnx9ufaxo8LDSAqWsH8GRkfxqtND7VNQMK4Fh/iTLXV6aMf/v0XH3EecB99f39Mf6uWhUyNPQlIMHhG30ZzHnXw32HGWgkhkyITbSg9V1FERN7ohQW8A9tFv8OuNRZps1es95IGw1pisq42NF9CCXKBY2t5i/VS06sB5h+tkYSf5VGkq3mb6rO/AZLxqDNNSJ7KCszpyYXzOu+4yhTwy4k9A2a47CwiTzLGgRyQb06tQNY2AEpoVVNuIVygbv3e9CcZjv6ErSAfGJNuBqhHG6Kphor4JZrJmTEq0lWunte3KAXpRHjr1QwP9vym8HiMN2HKuJjFJw5+ziwZtrBhl2hk6IYac3RFXsDvn/oyBipd2mBa3Rez4l1x+vc8w8jEIYT5gDHSOyO7ufnLrGfrM3iKDAujCdFzJUshJgoCY/ryuLLieqmdWqDz2xH1fg/2t2mWzg0BViENG0bf7NdzG7qzH6y6xrHFv4uwvKqloEdyetwT2WgvcY6/U8CQIbbrEW1bYojYszxUQAnb527OsTSZMqDLxCEXoQ4/GeGceaLqw0EAHYplDC9pF3xNjXbAiW1VY6WKNFtl3Ml6/2qAL6GzPLYoMFWgR1v+fhnX6vlJWxrGt7VWiqpvWUKfzyssfud13LNxcwx4sJVz8ejK7jgv77Qo8CHm2pJgf4UWOFL+GybX55euGZeqDc6vYeDV/dzBD9phAvSE9xQqYGNXv/dEFxddPxtdHiDeFULEekiLa2svfD9qjqWOO9SA9UgIxb7ZORqZK5JWaiDjUg5tvC8EbLyX558cyChLgvliXcO/X9MdECYBpMWjyHBGIleEtTyczt3UjcBXJJroTRAVhWDPDppn+RJHuv5Cd7dccCbbOJO7EzoI4A+XyA/sYLoOxyDDVvI7oglQ9wQbyhiDZIy5KLJc75IKKwRqsllIS60gv5a53PuQ3UBnZIYCEGhiCCTLNAzqL7aZlmigdoHFfCnKrg7QDF/OP2YUH2NOMJa2mh1uutZgsqjqXIKqlURm7E998QOG4iwHd+576/UTHoa4UyzwN3jWoG+8Rt1lpuyqiRckEfr/vB3W0hrKHL+T+rcWwVtbc3dU4Rx5hsHoSJxOzTfnAyBAJStVRtm8qivv4LWBjyPe14bZ4+BYfPGiBNdT7m2d5M6c4CtiqNovfmdLTuAEQmZmdcFEPnT8cFSeDp/cuZw4D6c+n9knCFj4T3ukaI5cuIm09GzHti1B5zCr5mGukDRsjxDcAcd4OYjpLFmtaHJf47VQ4YgJbhdDyl6BAKrCqk3nHbUTnMDS/1mChN/NSqmznLzYns7tlrm6Nwp+xSz+X+Hm3FnPd40zDpiCpIGoEq30DT7JITtr25lIy/po7lqbrEBZuhuNL8vz/k2hh8d/bYxjCbJaYBASN7maVeg/wjdrVPJm5oW3ODnsoOw9pT4XQoTVp7YdfFuKGIEnphrIjCMzO8vIvwAAnHZlQ6qU+FMTjuqBgaiD+U/4RJCtrvgcUsQtW1+xeilQk4nwOuJ9dd0mtSW+2YX27tF2RrTX7Wye8GZfUBfUzAOOj/NbZYdce/LWClXdTUFpyHMH673BhCZVfFpdwKifOnDk96rclbzRJfBT7lzIYqdSyZxk21hi3j/iu9uZimdops2rzxlvqYd2PYOfRMfAM2zzqICyGF6nsh9belAWjnHce4hkGcPY0p1xFoIN+RJOUflg6k86nPpLeCuSWDkBdq87uv+ANQHhOOVqpZZNLvfsSlvdU0dP79iVGgbqZ06SQnz7Hdd0elReNH8cMm17OUHhbLlNCWBsOi4EtSgBIaCXVHo+59K1zhsTN6xScR1A/9UDl6ToSOfutFHR3dGSriRUnpYloGzyB74ozqPKVMrA9YdVV1cCTzVvGLJWpfHGPkCy0DxTsBNK0MYxWXDFzTKO3ZwUZlHZj20UEqHe3O6tg2AgME72UFOT9aPZ/errTwDVKip8OLh+9O2ZHh56oN27fLEDBqBTGiLBdfmkxbeskBq5iY38ZoCoGp7Zlirkxk7IDcKxnh2bf4WG37FBgkYtCVN7AR8h8lOsvwLurXX9mvczxW3kO8usWT6SBOH3rwk1qZBD2oJHWJIHnDKVljh9lnmNdMW7DY9m/3rqbSU1X/qmgUDLcScbWQboRIJiSL9ruDLFOdi65Qc6pn54Utr2YOQpqm3Va6SNgQIytMC+DsB9MubUqJe2wMKruIVQ0/A6XkC6S6benIZmuoSyWm2fKolo7iWLcw0aQG9qAY8hTXWzd5DhR0IglH12+KwiQSzFBeKhmQ6OfdtZYBlU7TA2pcdGCdXqoadOOko8T8y5qwGwHZsxdgGhhEqgXx0tm52V1/T93rn97CbPpbIBLDkcmwHL9Sb3r9nd1dXJ8VTNKQMrFfGXrmWk/Q3yToZXDyb07bxCInVMF8PMP/4/o4sKPM5rp5uahwxfdOVDsI9Npyzv+fdtLf87DwSeszdGmVPElV8QFF8F8rGxC1BBUqYoIAON9Rkb0pvmNJU1QunkYJHwB1Qf2F0kIF4RTcZzUv8txKsMmNNsTOyk/YQCAm4OdHUjYOh2Iw/Cp39e8vOtB7rl8+/hyLhDaONbIf2hqHI31CHSewz0B5iZYEp8KXdnX6nH9JjrRfGTWKCC0gtYbquHDbNICzwf6QjHB45+k3x4RCUxORGbZ7dozhUrSWQ4/pyM4WSNLUaxi6Kr6ThwdfARDPrc7CZZJlcCf2dBsFGfMMq4kCtWwbMWQnAikrP9epFgicqaRSvyD6tRALfEsiMamc7qGL8IAA/RwBLrADGtXRjBCNhPo/XjNyi15UD/RxZqnY0WUzRccpkoI1Y9m7q4XDrU+kBhcRDwFd1dr5UimjTQ5YBNfOWZm7fQqvNSp3Ke68cKr9coPSRfFME8iJU7murKo5Y7Wc8Hqdm0qXb02FI64e5BudV1fCoRsBusMlhaFAsGkZr3hP+o+0c4/chRVTX/CYN0eQI2FrYCatrV9jLs5U+M2qw/L27IHdAMDUyeyZBqSM15S5LuPQoUouzvL1Q/wE+pDGFdjaqmnsaACkryWJFEvMrf40Ofu9ts8x9J/vBirnWDJJa6N3OualPCrhL8atPPtuq0rUgGAk0KzX7Lv7DLtbH3sQ89Xk6+rImJZO2s3J/RKFafY5fHN7tTsSOEGMtocrp2JzuqqxsoVmS4CY/nZYZUTsnNeLeBEuntE/xTcYyu3pC0UQDaP1o77Re1PHmjLB6wDGMPBnMC+V0+dEa7xq4LhjnR1t1pF/iKfLsQ2xxGeySQcJNb1veHgeRWiXRimiLuKl23l2oQzTqYfGAtw5u8+nyksWWY4fyQBFZ2DGKY7YVa/7/42B+PsYJkv7Cnqxfig6L/p0Gom2pRlQAllbkCSXbcWJxrw9yTYPW9DF6nlBd94K/xdyOknqY++bRKnENbYKf9uCr+v990BZuew1LqGyp1n3HMe/V1SXa0JP8QQPjx/w6Zt61hZFfu0PTMWiFxFXylu2Xa73Q6iN20DR+RYWCYQzpmUFOddl+fXxzgQA1ADpAjyqpg0vxQjWUU1izYkKZvxFlrhcqTBlbwgHaI2ciVZJxoJ3513RpGkyskPPebqzs2vlPL2d/nGOn03hq+iNxTDb+iLVTxO3fVxV1qV1SLC+aYIe918c7fF5EzaaOIKVqo70Pa3njEMFwI2IQWKydtrV3121YQC+h0n3C9TaJaxr2leQJfLE/WkH7k8qqUnsr1V8eiPNYewHFoZpvy3ok553HCWLSZUrFNPkrjU/3AS+W08BReYDGVQzDg4eZPYwCmNSb4j31wzegAzO9YouZuikHz1VGz+g0qPKBcPjTvYtM0BFj+Ox/rGdtLk0dNXkLfBGAhlSz1kLaEcox4zlKzcSUPpVQ2u8sPp44B+H5aRzH3om5OHoCUcDADbHD/Cs1dFXN/bydIklSH3BoZ41zuAiGrNvGdSGlcJKeoHPsxQIvSFqnaN6pO9VObYkzGVRoZyaPxu5f3RFIvnDIybqJbU+MmhYAywHLXNOfxjzbh7N8IC03TenmCicLAO85xOSBNhYpGT61FVhjFaCbh9TWs/AATaR+g3pbyaxxjzIG2SvvepbXKi44AR/Ym3FqGsvHG7KtrxpctfTgsv01z4d8FEpqT8AL1I/noqEANcb6nEJUYnKlKZdXYbU2Q4JcFN3jg24EnMsBBaOSxZANTClPYWO2YF8QjkSgtkEpiwRkYI3CF/S1PG9+a0nz1iNIRRb6AJ9zjNDBAloXYadDKIBhQJSzo8lz7ngG8xV7CMeeO3lKBKj0njPi+4wdHWTc0/hgHAm+yThEPMdlUeIZWDBeGvhVXF9b2bxbfF+2i3hOz81i5uf5/m3vCilVVXDDFnECOTAi4SN0lV8jXy0n06QCH187BObk4pOkkRffoWR41D1e4XDrPpokH5gHhLFtT4qjHitwWz/EfxrwNSHaYktnLKJXmmC/WfwvSXBpKMUt4lw3QnFT1YR/svW29p+M/MKHNQNVwUSIKnjphRoFRkTe005ye5RC4mopIet+6Jmini7o9fXPqLKI7LskaKPCnD/V5kap/OsSIeDF9cx0FZnuax8MfG2xTksJgrDw50pgoJAEpyNtYTTWbKW7u3xzYn1TltVqDVzaYlZEpv/3RGozuYJAlbk/S8los7dF1cMhfvBubGrXD45UxMvP90udKq03isSWr7PqYH6/I82GBi2PALgLuOU5GhsCmtvhlFTdTxt9f0C9mvGE0K7tVC46vRaTRrej90EDbnJnwzYsRlcmewd6/rIH+m1uklCPLo2sWrysJ/PYbwXBnJwucXCq8oRp6qoC/37GTXaqYAc5Sn6XNa3vnoAAIvY+L/xUqpHC0mPUgSXWDxWr3UzmzHIcmjzuDIX7OKOZbv1L9rEzt8YUip+1FbKCoDJCzxtAToEgrIbE9Zg1VZnFfdIfe1NdMnB9rSrUDUvsL/vcq+P46Wx+VUG+Jm8b3PeH9y3ssy8Dnw/VynsZlmqxKtnefBjC87epQGZ3twjgMeB9vPui1Chbg+nLTBzCaFxOSH/NX0Eh9iI472zPQxwk0u28ZDEFJ8TbVZBBHot7MhYnDXihieqn4lrnVXZPfxD6uN1s2oYbKxRPK+5pPuQzfrouO0HEZcYJZsdl3youilvDPO5n6zwJMA3t4FQ2S03/o1StOtnb4JxfIJu+e4kaflH3bTkXcGe59p4nzqic5TJemCJsp9kWKx3WM2NHpJQnLQjBrhe4nDsFAJt6zRkR+BYWFmfzkfBBBFjrLrZmZxjhAop0WQ3dqZ+WGE6xl/pelKEE3Pk4yti9n/uvHdsp6h6VhBUQ7Xz9X0BFYmUwLY6rOJymYOycHHyxX5iTiHKD+qQHf/gwv4EqIAzr3VKGC0wYCTQsQNuf3K8orcYnmT47vFlOJ95EzfIMvTaXQNhOC9VvB5JNGSbbA4/VsCrD8qoTK0iQeKuFl3J9Yhfr2btBX/f4A0UyfYHNSz3ta+6QAe6O97Ne6ORcuwFHnVYuiyidSHKSAJn0UrLwIEwOk70tYSafIEaX5KT/1aT3KXNFbl5UyzSEAFBMD/CCPzM9imej/VxXQdY9BHTLp0Z8zoTOI0wjPDbVVf9yiE0si5t5UUFOXgcqvvkxYpxD+TT6Pkn4HceY9WrwbbypLzoWm2QR3cl3If+XqFsaANChpAIxtWnchMa3wYICXNl6SIUPgdffF3+EoVfp/HfpfBHcPiHIPPNLmZ/i7B6HGpZUycV3gnorIVivYZsaDTcDX+BIuJk8vt3VUkIuoyi93JWpE1j03JoB10PTzh2F+YhTmvYVjZ1yK7URrTV34Keqgdbi1G9Lo5urqD6YnRByZwsVHMI68Q12/gF4oxChR0QBPcZRHVYQ3YRKD8ZwfbkEtDHWbKBLIWJ0pTuhfIoXamdfdjPRrUIY1+ZH26Bws9IZJlQXzhHLtLNIxB5J5eyvQRSgQOPiV6lDzHZbeDkciay1oJd7pn9vz4zwPnohHus193QNfeVpY6oUjHYzAIJUGqNLVOXbY8JppoREG2uo3vK+pDI55RAa/Uf7747fqpupRxhYw32G94S6CtG5+rVInikmv4ArQ63JXH/DOvsqcqJZU6JLUN/3GGj37YTb6bdbi0Fj+NswEf9uMlueqfasbe2G7oaKuVuHW7k/YgrxWXsTILL3N/sd64g7fuxFimqTj8/akjv7gbDQX2TjBMcTb27FFG5grYO1IVGqnRJbWl+NoF6Aek3UwMcVuFrlUN4DCjEgVPYKSbZNC4oVcVWxS0h7+QKLpNiqT9RsjnsgYsKP9+FgvE9QYM34AgnVQcUOfXa+3yIauN/1QL1v+bc3iNcGKs5QAlNWU22E0WI+t0BapQZ0D/1vxgihHfVE5Xbni1mVV6MvTwkGF0V9IEAJ6Ylwx9ibUEiw0FOK45Lov1jrEqEcCg4+zYKL/OaFxuEwpBfgTXY+jzfy9NV9ArmK82AxABvg1oCe3BEcpEzAl6M+TZVjECFLG2xLFur3XvdV56OJlBSIKs+IyYnTST3otnvKhDYsutjMFx+DT4LUciFPRdLqDmpn8BqSxynAsQ+PM+0rXXoY4GPWcTaeEC0PUBdztcHhC9GGY9hRaYuRrbRvBpWIxieHq0zFJ4GXHgCEAEVSYWJwBYtKDN0Nt10brwB0jQsYTpZ/FDgI2VxOegjA5XWBmYqJaNAXuukGdX31lruJT6x6xzAx13suYiyGwlQwGMJFD2n7virZ4GC08lc5T4Z3eesZ0gonXL+myfXt2FBO+i5GPtsdlJzK4uXAClU8zdEev16HGhiQnbGVyhQ9V5Jq5DCKp0AfaWci2sO/6JAuK/uxqL+7UdadrCogXVgY+ZB4AkPYybjT5srsQWaLrmcK99aq+Cx+Qgp7qOOON+I4ZdYC3s8hHUQqo15R8DoKKIl96ATC0y+UNGHb7QIvzRIEZeYj9RChDj8M7mEHS9MB9pRM49BkAi1njDTDY6cIEWMrGReeiq6P6kmSnfj0zJVSRQGzzL0Yimb8QPYIzCkNZLemCGKEZG8FWfSmgLxFIXwNSn+3Hq8go5Qk+INr6Fsdi9g9OObotKHA5ywQ3nYeEebFSQ9i5hO6fJMuLAyFtIc4EGBHIiE4NHn2TYpQA8I+H7RDwl9FxhpJAgmU8nXyM8pq/d+KWBkPJFA0ltn7BsYx2z/Abv7119YbmBNvCsQ+hoBsSPVIlF18Y4T+d33bt3cIQP0u0MI+2/vw8YWXKCNX58JxeVjM5HyfaaTOfjXOJKfoWzmknkfqPwoKXfHd8BeUZh8nauh4Phe69WYMTJHo57uoxT6ty0JcsUWEpzgUI5mgzO4voUUMdl50X+urGkO1eSqb5+Tj/gBsawEuGxqop8az+e+ZGSpNRSxXxBgjZKJ5o1c6KaCJmfNUmt2e/ilXFCsu636jfXU1uoAnuOnLNHzXWEXu3qbDo5JD+FZ3AreMF0+9ymVdOHOweRp3vwTNTxdItpISglbehh/HkcwZsoALGQKs1B1TJOuNC/6386m5L7tVjNYUN16OglnTkNfd7P/PWJvTND1OXgn19RuyIG67cr0/Z3a44VVVeAmgO2DywCBdFphadzFqManWDg3im1wbCtT9aabrv5tZjaNB8Axgu2yhuPJodEl6ouDf9r1FbIm4AxiIYHc2eKcdcXmaOKObu0uWx9oXfVKGB7wz4N4hwWPC1MoUD7xBtEsTrUjUVstDBcIgQdqJFmuismaXDyHbGrsDsPwq7fvW89rBAwAFFl+X4c43aFY8QdC9Uiwn/w8jTM/AEJOsbase3LTmKH12U1qMuzN0jd7URhhUhoz3wTDKstmiU7ybwvj06TX9C01pBZ7o2mjVEx70QdaRs3DFC/tVnBGuWLcr/UI/r/mR003koQGYlX67oKPcgLOdYmr02RMvhlsdqcNimkrRts9KDPcH5kCq3FaTTBHSwM7DKosPNfLpemIKG6oi7Mm1dNCj/bvIUe48mWVIsmFrVB/kTMW2SS6swO1WKjRSfYgPO1ZXmQeC0u+GkmbuCuCL78gK3Ac4Y59nnZonoKOMt5bp7i9atiiuUolSDA0q4+uA7d33HKRuokxTfUxkg8nDP6cpgqRi2P4RXCDEPxqCZ9M9W3M5ng+nnDMZOmWhySvtBDVMPSC7bcxIWU3qk2S8Cnm8nSL33RfMJ+RuiMRDtGJx6l3170dHfegAOke0cwT1z3i13wt7yo34PTCcRvcXsAXFjNb1fpeljcQbSjmWj9mlMSZLXe8BMTerF98kF9o6uc25/DqyqoMA8MDPkR7w/1mQOLcqX969DIn/hFWHlAQ5g13SSESFsPcvMfyPG8FFaX272I90QQUv8HyO0d206i2vl9tXFi/y1hMhlUZy/sMAWhPE9utNSk0RoqZqfkHFvwsPVW8eKY3CdrhPscjFQ1Rx6sPk+hJS5BQR5LB8hYRoErgTuZUy+0oAr/KDW7uYYN/NsRIiVjC2LJ81Au29N5WKjSMZxv0oSp7v05FLv9mIfeAocPkMRydWRVSdWo29hCLeE0Q/aBgMOFOs+N3Ywsg+TEetMGiLpNuVLNHPuyjUDxvB9f6SlVB7IGKmTtjvDqUXjMn7Uskkiquvr6LIaudK+zk7YPOCwxf1bx6S29ONO8p+WdtUFWMK8tXrcQ7lG6Nk3aECYR0XrMThokSxReBZyXoD9f/SJ31qna9Irp4AglFgT0hSivOTKUP86J4e3RATWUftJfsTlsObd7SHlqoGKf1Whb1wNa7ZJSTLAvw8LVQlsTIDRjfs+LvyJUp/l97iuHFBlBJ/sToeAPaWxfRHvwkkDP0YNAqfa+8rAVtX3LteR/437Be2Dh1sOAwH+y2p3H8lwH8MhikSwQrnuhrXLb+93YJIsI6aYZpkUW0cOmsijblV16mVEInsOomkiYI4ZExN+yK6oKgfHqnKmigS6Y7TQYY5DifbY9E7BJkp4Bm3rctqiYgibl7fOCpxT4INNJUBp+BYO0lGaGZC1H5ybdC8RxdSx14TrMJwV/k58E91IZ8MC/Ds8jSZHp0dgyMZetyvc+l13fw+Kj9sx0eFw/P7ROZR5t+b5KY6S9wFHHCReoHzDABePo8jLwzjeLiS3fdk5Eqtp1SUDSKZ1Ii81q8VjjKTBqHLJeDP9nFFkIhbY8C71wAU7MPb3sShnD9TX6QjLE+OLd85ntm1DGd7LNMN5YB4p8FgcsDOziz0KuuKBOg/nzOz1dw9Bz0ICD8TQDQYRLJgazOPLT95v+RZfPB7gK9KmJAa9wfhnUOCFCChnjSvkWQWKwBiHGuj0kc0X0UWkkeWgjJeL2fmvnBA52w+BER+Vj05FfNJnlG6zjqkoC4WlUzMiF9woWoymCsFBQPVDdZY4nqkWfElH4YLASYxuaDDn8gh5+Zpr/tUXCbhVrevjX/WYIuB2jLOV+A7PZv3iU/lvvXpNIAa9mk+C+C3XVXPXmo/Afi4gC5tVwGOXN8OVjzxpIZF8UiN4kiF/RVmLuxPwP4Vd/YGgAVbX3VMOCrqaAMZ8rnU7+F9BK6wsBSerWy9aa7kWQ9Ht2RFFrXN7mbEgogOtGwdlmbNK0cn+X8Ftv21olaUnDB7ZXBbuhStT756G7yoIdhQ4XMVgKcsFzcG40MXNlzx6htnCZpI/8WYVnSnkEwQt3/+03adsveSJH1DOZanvwCbLKureUXrkRuiSpIhY8uOhdInkcQk0QN6DJ7iqrDItMaNn24FYLQqdFNVXvu6XVYwwW+mGtxtr0I5BfGJTlpyk9EMMD8o6lbohN8Vtbdu8w4C2zkZsC3Jd3cONJ7AXjRj1vtsmYJ90iTMw9qhs7Yz50Qyt5gOQ91oeZsmmCVXF5YQlSlH8ZTxLSWmeZeOO0IzbNprezfOuvOFqSbDhWFtzhP/oQWTqdZ60THeY7tjFIY+qEJsFUEzpDenrVBRL6KMhjdANZLr/J60nF18P0VyFcHCvlUu8C8wfY6JCHYES5sxt8st//5DVdRIuJtwhkNoC0MxIGa9wet/5xKf1VslJvGNEe9FTRGfLGqHFCSnRlCM5/0Kow5FwSvvEfjleHWbaREAyuiXi5u2Zjovx3vGBQXGXxjZ/w0Kr0fc1io59DqEiIX/+hdcYiNKmlPaoCr+xGxVUPqtXI+hugA0nNLzAi2onq5r0D8gxQJ86w/6QXUgIZvFD+mBd2Yv1yict+ItE217W9laUYXQliSaln0CYTfjyAOpM5ICDFDl0kAQmZV0tDuFmqiXgxIPk8jk64VhjWbHd0iOc2FXFPySGFC9olVDuW6yYE4MD+OZdhb7ihPYQfXqZU/Ej85B+Q+ih0TUwWxVoZbl1F3wPKt3TPhCfRy32WQrql5gGU6rUz0TwdW4hySAlu+18/LLdHCJzlc8Zly7nbLCSUO8+tAY8PI8ajZkKHAyWCkvAoxsMZcs1P3HaCI/57iL03pm+KwX9E56FyUgI7c/7CmmR+vkH1n9UHQHJHq9Bjkdb72G2GU+gxA/O+G67rSGtIlAAb7c7g8aZUY/pgHuG07kMCvKPSyv8lCWiaGb1cj4+MnDRBKE9EAD3K293mQOmLyxVwXeBs0hbfh0HxtEqkb+1hC9p47/LpzVoHX4JR0ADMGKdLTCaRvWytHdt74a1Kxno+bKOJRdyVh9GfFsJIulpVxoo0lbnQiB0DHMZRhDfeYZu7xvb8nf4948h5aN/1x2dIuC83ks9soMka24Nd18YdM7+vS/LePgh6GzDIceCCXqqGvmBTChMg1MrT3sgyKlcq7tlvklu/5BuqqI0GS9adn3HHgJjwhdasTtZ7UcafbFFoaVaj9H1vEf67QknXGOC/SicnkO+dfJ7mOFNCrUiI0fZnr5H3gH5t3uHE3OJ0/qmWA6gFlgrGunjRasfUZYwC+y9zDbdjaSv6wkRlJyscKxuLOAGy34ogRKcF+6H0EXLQVoUR+lu6yh05TyuNEXtGDdKOLrr4xphyrTVfWaDZH3oJKBoK5aGHhU7DZsMmYYqYOB214hztfWCrJo0f8pnXMU6invY5o0ouRrrBkov8K+BlyEw8yVOHmFlxB3SRUIuvtf6dpb+A6+LiovLAoEaDHlRoEpIrUdqk0Q9uKTbfkSCsN26oAPHdrZHcXE77QqDRllpa0Sjw1qm6vQtq3e8hitNiepNF86lAChLBJyGcnz2ko0WuT7BzRXoq2uRg67wByg/hxXD9dT4M3SEmhmt19faJgtivZjiXGU3LQCDX3twbF/QuTPfAdTEwlwvUaqr8PJ1z/FGV4KQj6/FPJJBBATqM4i3qCBBGh7bXJ8TojGJOjK8xmJd6GUofqb+8HXrwE+9EV3ZOPbPQJ9swg8vZxoJHCOQ1fOLFi7Vs7ztfA2i+ykMcARDPJiLZDkIdwFyRurJRIRakNo4fHTc6NfgFAlwzFSOF3suNkCWs0awmjJkyNXdEIKq3sT5AsMGNaXRgZIJE3fZoHQ1pVdUyMtV7GJ91MEK4uqg+VRjopYTbPIbbeulq2njZ/TSzzZThUg0B8Q09hxlLBNOi6tctF5UNZSNfmoN0Yi7sbroFlgrdGnHdu4/JjbeMAdaCCY02IKyWRzFyqYMXbjBi9fWCyRt7qDQveoZ/WDL57Dh2z+PkQfxUQ/zWryQS5Gx0l8cZ0sdiUmndtsjDEw6XEkZt4i7pekGltwL6X9H0k3GGT4U+RLi1+6FjJNugZCJwCQXgwOurX7/B1D6JJQFg50Waj2ipwDJcaW+fzLuF+byzfVI2Q5GevA0qrEh1HspID8bPgt9EP+BS/iocPLkJX52wAl951SJd1Ne/oGAFUv5C3HOqtcWQLh/cmApRGtPcw6Wkapwpo8hGwsKDYHBr54tUBroqe6qCg7xenyoYIq0D/S8c8XmIFJ/I3AE5GcRZUsBLSTEIVarvXvyAyJQeBWPRsvE2tTZtMGuxS+20Rqxy232DG7lmgrjLeyY25t+evmDtlS6y2roI+aEoBuGeycqPaoIjDBdd3UnEFNU5U4nkoPbJjMBS9JgEPuLnX7UAKezEb7vUbl1Cj/5TwSXjgGYKpgODs2hA7SvJ1DSuftB29WG6pEqjt4mKHw/cOs1X8PnpEQ6XUIeHSZkM0w8UCWrHJxVFtck/Xcsg3dtk1crzAoVzwO1Grjg731jVNNJrQxk3rV4WdBBfpHCwG7Kk0d4sAyLrxDSOiio6aAnghCvsWRNV0Mz40Fzb/3OzExlNHEwA9YnCZi4nuwbDJiO714okB8QbiRMJRkPCfdU/r0NzytET8xtpI7s5E3Ol8yUrWJj1DNM7gGsxeUG7dD7wGOpA7IYwqWG31525E0y8ZIytZknSLcN35uDHJ8Eym6lqdxRdg/uHLpxUk7SL6Dn+TIe+eii3ubEj90lVL4c2joA5puYslDoTaWrsfEHJ7iyrKGa7g5DHWxkcB995Zk5coL9hSowZASKdWMpQ0HR2Dv/ZnDkO523WXlF0F35vTkIxtjjn48CUXMfzGjmEhKOWACYonLbikFqpvQ/VM0XTPSbmQg7LNw2FUN9itOTb4aOaCb74LC88F++KJ4azDVYVpxXC35bfsqdgK2lngxfFqhMOGEYe73c8l9Ti5gli2PejI6Hm0y90SygCRfiI6fOa2qBoMKOnoLyW4M051d/uz/Q3vRIgo1P0Q+LmgPlLrKjxxWE4Bz8pS3H0OwC4Z93RPMcTCrhAWmxmwSWNNndKUdI+0Cbkfl5NFeccJxVvBNCDiocwbXMMekEFPuotzsvo9lngvUru3K8eFcopeLEGL3jR+UWaJHrk2TrBBkQ0LYWzBJhp+607Jupq/ElEu26yMPKXR6iXUkbPYK8X4grUI47PUy+1LtCHadoazQVT3YrnDkjVausHVJuhSkB8HGf8uvEfustVvOxc7yxkqMj/ThLtVCXKUFbo514Q88t2deE0aslFeC2QXc8dd5MfIrdvDwRXeYAidIUcj4VX5gt2Qcf/54oL6jplPcFRBMhLBc5d0GzkyG+TLqswZywo6duCrgEMf0KJL0FqUoAAsAxpznuCSr2YTMBXza60MnzBFouGOqECR4D2/6+fbtJOUWEuuf3i8zUQqdJVuQHbbOmTX/TWVw14Nbp5gzk3pi6SdGS56VW+/tf30XRCWgIUvvxcIdWWU41PDSyKrTiGhnuMK3H/b4dEm7DaK2lAm82X+Kgodm1uebg4E0ZvcN/xFx28XHAv3hFd0JqpIyLXcLa+ZJMF3cOJqINMgJ/uf1ZZBCHNWbY7AHPm+caqMzXDesYXx1J6lzFEaVuOpTSO2alVO+QxSTNsspNCdV9P4VrdtmCt8uthsLAkDlJuOdxKHzMNcg0X/f+pHKZSCrWEfku9D65SwSVBkTi2pwsK938lkTrSxPJylUfTwMP2x0FSfI2/nVVBJiZlB5mW2JCdW0/gGxtTCfxdIIzg2FvW+mLs0WTZfazUrMbQFFuquta+Gb6Gb+2SPTAaoNXGJPh7K7ZL6VpUTrIhzizjFM0uQXa9r98cf5iVRYwd+rZOA6igLquS9HDW9PTCovyUpCMiaSBVGpaT42g+oRg189L/KBHkjs78sOXhPEq6GW4O9BRotmFpBJgW5MhszrALMyQ0UoXRu6PtzwxBM6fZfcUZiC1EToOB1DBnViKwFtCLUXiZWQqZubJvIniUFR0iltSENPRFEystHmLOyusYIsyFK37PGaY2bC6GuSkAKZ4uC6i+qmPeroh3Q1nygH8FXRZsrURAnxmupwMNuz0woWtbK+y5X5L3hypaAU3Hbhj0hJlJkkpZtplYAhNKuHByrdOn2A/+0Ls1kn++XZJoZfM//Ig0i3PR/d/08dGitolRuULJHrdZvVsGHSIj8XjQZqGKcMlI6C20OrU6wytTx5GuINb/6XglyLCLUAl9vPzIz6xay+tdR9FywQhTDedF/Y7JboQl7/RRSYk35ungaCIDTdh8OwqMJj/uFKrWYFRSJ9GZyU/trS3+R+1mV8M28KGNBv/xe/751MjEaC5bex/tcoO1IiM22vhOdFQe591EVGYw6NwJw2Sfk9nFnZFNGLEVncVbgH+7KE142Ekx/GcXUHq0AxwdfLx/cbRek2T/Vk4Q3vkYOSXmk6FqbuKddTv/z/Z5EF4LMV0OrJvIkepmPTpHX8PP1gEMn2nwsd6azE0ql2KO6nh1SN5UIFvdtJFuh6f2I2NsBkbG6lpQ+y+zUIGjn4KYqeSS5bMvk0rrADmR5HjxI9H6VH8GKWkThx38o3AzcMP08yelp4GZS1tJbiuXfLoOFjBoyFnf+0vOmXmzrbn+xBtIoWmBT1eP1E1tsJGOKLlLv42nMdd6glcxhx/NkK9tInZgYkrlz5q4ENQqbwgYAZe6a1fcKkPWXpqJLDMSlfFtc3f5E0kfYxbDYKY+rH0PZH2RPzrpOu6N7SaXrNoDPFw+iST6e6OeG10Hw4I6QzPPTY4yqFTP5/ec/wXu29bVhVcNgnYPddBo8dh0682XdpSMlLzJQez88fb56smkUlxIVpCBAojB/UlyTVtxEk6IDD91mVPrILdLHX5epz4QXUWx2VUOH2zpV2zZHIZZH+0RVupo13g9hirIzGobxfYTAm+no0p572sxAjUCgPiMC3Zz6Ks+qrWLilGMIhMYrdKk+r3H5PxyN81BPx7vErZwuSfCk3PptawcEvnDaP04XgbZ1udyCG45MUOzqdW0wBxj1MVyP06NU5n6ZBU626RFnO0qsCA3oCiTbTs+QAH3QOQ9sQDGqk8ylCzVpDSrhvctRwJBw2as924DZP8fhCTI1svc/c8+LJqsIfAR6ZdzIBGa/zhBTrDSZm+zlI4zHK0UZDLVW/DM0SXy05cfhtgdWIN2mXrSsDy45pDPwuOi4x5NJVAfLRkKAZCF08BS8uj4PfzX+slOb/sCmMgRt5VKIUdKxkkbTW6fzSwruemdIX+N/CPpkKr8TAg9/BpD4Up5thQWmO35GI3QFwZsz8yzHsqLc+ooQ1p6Uf31Cd03t6K1zk7yEet2EzcnZOOBliw5wZC7pBAVCZ31nKDWBRb3G58C35NZ87AAgQTLFF5XJ+VX4ADPVfrtIbB/YQf5ok76Te6Nybei+MPH3zo/3oG74+Y3J3ShYmigN4TvU9Jqurn9n9MslVyd/nil3pfRv3JElLKYTPe3n8sQl/W+pvwFayXEZSbiyEq0CKC7yQKER4dFkU9AciEMAAI1q6mbgQSc3uZEwaKTQvenTv7Cn1V0BFESuhCAImxmtCiSLtFHDwaoBXweoFp8h3lzMVYUatT34LuZ2Sfzjm62iC5loxdxydV2AdYLeX9tmmln0ineBqUXB5rXYchRxPWvZzGGQDhlX36k+qd9J32F1FAdWxrUUducpzEv8ePpEKXsLhGF++6g0Q2m2yADVX4IVxgol2XfiQiqqTqh8fmALto5VRrTfC9rXIAAJcOYV/xhLD6sBNevLASLGq1Ssq8FBHRdaR8PZ8jZkvleO8gXov9XEaG7Z0CXaiIuG/Y5PhvXFT0pDs+r4PaLi+c+xIhZX3e4sjDnmBzmy8t7eeGGPX6dQhzvTfV4qcQzXqytz10uc+WMX08Mnr2fIwaND97KbqXvX9DlH5DWptdFOMeXq5Fw4dhVd+VAWYi7N0g/4/0PI0KmYoupNbsL3jTUB7+hF3fkY5/8o09HBxJ+Y45hfElxpluO86Uwi4fQivFeKvSGIzLlALjjcuCkljFC+VbY/NRv00Z0Mv+GakDsOHedBez5WlNC2f3CpzHfU5avFpNBQsyPBnJPaUfLrMje9P3qhyNsoMNBptOPSauBK2zw5mvw97BV1+4UlgAaORB3lLW6O2VYkVTh1U3WvTmJcUwkOn5jJaKSrlDKd48XR+il5vmmYrn5pdrjMTNTYMrQKCBAGrOzlqTuuGDE71DFHOlBZegUiRDOejyv1rKwePFzqSXjsbmYz86HKu3IF1F45stD3yqRudxHwXUl5rIr67I6TRnrx0u+BlD2+wb3A/sIqgqGEVm2EM/MtGCQ+KlWxzhi/jTKnVXE+V3Yb3+ub3qEGnXmj0B/zvVmEYiw16mGYgq9gXw9bJirxOzmP2X5Dd1uDWd1oJcKjmzr4aEgTT6qQ5bd25Ry/TxxB3bU1moqHdM84naQ4M48q7z94kOh/5Zemxz3a5a3Sv8d3rBLnJY/QuWFzXnBBEOxYNlryJ03VKhvRYFqHKTiEZYUz74AHBisnwoJa3qZ917dis5C3ld9TUaEZjsVeIMZhOFBe++47d8P98O8fLhWZeMz2Ti9E2x/c7OfPPv3kTI7Aw6mPHAwmMGf1PgtQziz9Whw/9IPSHsdnvqO4SUI747u3jZpola/fhKMlDiIjNc2o0nYQNSNOvQZTqq9kjei3gLM/AwFD/jLaE96RZJxg0RhyAeNS5bd39DyYJyNAGwZe6HqnAZQMtXoditaYp03OOf/zwskxI2hWvkqGwQzKIhlkb2uZBJMYBfvo4juVEL1BoZWKXfngUCkCCLeXH7hIdnjC+yHBU2pGfkZS2Zka5VJNXwx+0wG4uZFOd1t1ftYfvHh1nR3ej7ZHjtAZb5ZWrqEuyYW5y/0GfALD8tJ5zTDzQNQiXQmFv4lNr3KAXJGkLmlvD3c1YjZ2ySaLmzGijr3lqpfK4nZxeV+K4KapskbI0qI5E+SusD4trwO0Q1gopVMQt0IuWs0F4mZf7xg5Ly24Nb4P1Kqy8mG8fwaYsB6CPvr8WYRWqjypmTTyKuou5wlSOUq2QRyVQoBiEGwzUSPHduCDhxVGsZZJUokE0fSfRKsHDMpDVfMcnbzyUVkeBRp9q770sP1UgWhP0Ym6abxDHA1q/MuUINeJbyINpZWkaK80kPVuDMSifMgWnp9Hu+7HsJEseNtNrPGWzSmclAL7bQhkdcjNKRustrL1/xSDNW1/QGG3J7OIX95UmwCNLweHK1PnJvry1bvrgHRqLRj4bs4wepeLZ5SsaoKpaX1O0M/47g9xvHMKvUSa81F2DbQKSMgQieFozYAKlmbKlQe95h19xTWVJl3mpT50rfTef1KyORxWxWgwtueCsEXGnfkyoHiLQA+toUmjuxbV1zjRDOc5Pgy4W9HfBKV3A3i65nVt2RIA00dtiVon1+JpYxTGxMb/PtzR1Q8yB9huLYDMToKCM8XC+lWd9JSG9AuA8vupJsgYat15K0/1/eeToSlLQZuE4qD7Poq5Pq810U9A8K3/8fuWpPVpSHo6+r6xahrjs9+exhl7Px87CHrs95cLS9RzCqLnRQ7KDqow+FrrHXkjpKDPrgoycNh2cCA2/HcV5MGBWnA4J6tNrjb74V3gJcvqd/QhdxM3xmS4AQ","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"cb677ddb5f7e5f961128425b06c54b598eb79e3c","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted:6mjqr/IowaZHmZRFDheV40UGsQ0sVJEEfQuKG2umzvjguvQXGNDi1nl747nCkFgOsOds5jYVCKsejZB5Ycp55oXbpBTWUOFuTcbJi+3ZrQm9i4kbql3UWJNNseqDdzVBXYHp7WTzFhQ0U5rqZB4uDZ61rmVX/LpmmgFuevs1x8owCRFo3w/YQxC110zOuoxFXRy2D7RBc6ZTQZk/Reik/DkkqHuXW1aYatf+BkXbpHcpfYrOqk8p9/VEp0mMj0gECCQO0Pqw4Hd/Sv3nADV41c6kckej0v9kJtXhZqOzBdsFT7mLWuylMl+qvHsaHJ0MDt5MzrpvlfrgBeGBF5Midf8ReNZ6ORrydHNfFH09xJE6cpbKTERWFXgTyuay7GSWk5DakToppKb1wHNu0axV5Iq6vDU/uFLj1Nshh92Rdd/Nu1PY5z+2DpuP/55wMgC5+trljToArBiPQOHJAn4PtzRb7TLb+cSeKIxDddZ0ZmkGII9iJGE5gsK+DqnvDEAnbNBlGwbz5SIC+7PUjI6rja91bfQSJVQleSXZt86XHg5MtKJ9EwDGiHfHOD5jfZKwxPWwV/qECGdRIM78OQo5SUuP6twlgFU/UnnGz7dRSHYYeoR5mdmHDNZS+3bThmZbxUgjSht5CiCg+6eaiMcph3vjsDgefJtfFegbIm50KOBcyFp/oS2o3GYLVYHq4Hs2iT2VB/R0b6N36KLn2i6o3cfqgzKAI6QQ1C7jRX+8iREvlX3lBr//FC1VuUjr4iORHHlHGiAYFO50FtKAbrzk9gdnSj/zENTdsp6cR32Pbikqe7VjE7lio3O6NQcNHlypZIcUM+6Kyk+NUxn+LDngSqWYvrLat+AA5GqBFxhmhMrSFE0N3KLrPKC+NdWo99CaBzTZ2A+bbwas+ZajkwtAP4yAR+r8xFyf8kqQJ2tzMX3Hu3fs/ZY5IL1SLOpUeolvQV1APALj4BbcSDmNdJ9+mzDyRnbHeUgoxP7vYaqUQhqO7QQK3q26sySlLGLC/HkuR8NMYBsWaAxDopofmdR1ATxpAKWQyqQW0bGBQOPISzTIroTNSM4RPKIH/wyC2e/stnHcI2UnMoRO741LRUdkDYjkoZ4pX71D5l0fIekJjyJVA9Y7yTKy0s6zBxOnGFh/5As6sWSqEt/KBUXi+w2JtZAsIgHRsuH9UkmJD4i/83YgEIkuaxKNDyiSJc18vS9qZfLAR3k6dIDnCeqx2EUM57Hw2X3lHksgjYxhueVcr9sltsnMjqSvWjTJcGusE+pg+8z8MDo4GUxQt9ZGaUS4ZvT+aMTcjHJXKoT7xs0XgHJMGzLEiKvjeO3Xw0Iys459ym3Ju0jEogWDGsNP+5GSkpYhtX7kVR+zPlQuTlNYPIW9kewpAq+PoPYmy4i2WKlJ01CF7HVyHK73SJ3cASCVTlxVlPoO8faKhwLDgEEmWBNQKMfE4WudF8NSSYf3+qVwzpVlXjK5Ws64YYGZb87dbP7Vc4Mr9KSdsFKOouyOkHfWjwGNOSjiMC/pL5mjRILIh7Lo+fccxeFT4m1nTHIQ5YGG8M5Zs3NJr2dlmf8BEc0G4q9qr9M+lzefp+gykp4fS4zsnw/DGl38T/eqr9Tq+saf9MLlHZE/KI/+soLxPv1McH9P3SeGZCVlvxlGSFoO1Beqn1guVZWP0T5Vvs0GDZhcb7HqkmxidrJAMfVnTde6+UT5awe/iqtB8M95DigmGKah/I9I4gqTYGRnHLI4C9AQR3yxlke54c1/hifk7Xj5XKrUXEKBxfyF3P3TY7GUMmtndNA9a06sonBYWM2kytc0U4e0AvSuPhJeEWoR7QGZqo0c9bdkhlRsV65XFj640N9n12eEBa4G96+SXbKVqj+zKeECjLiyMCKx3wDLHa9Cs0VK3KIcl3heMF6lMIzAZOKESrs1ltPN6CT3AV6bSp3F2jT/46EQw9KJYDDUJKdunvmZdpah00g56m20GiY4Jg/7g6Ka46DENUcU62j4muR/DrcMxA1hEfrzTjcGp+f2pze2z9WX5Mv7gC5W90ozOfEvK1HTP6Tc0JqLRj2U2DN5Q+PRfNMoiI2JhfhQm9Chbqmoc86RL3z1A7N88M6VPqamzyPLwzMBXt40Dh9qsi1tNVwA/s9TP1Q7fT3IOCOoclDAbadPOKQMQLHAwas2/1sFNyfDGBSuahQ0LtNbs5oNRHBkhLr+2DFiaeU8SSo9hDAKRzxUiCOiHNFt2XRd4c7zs46e9mJCd+pGIIDEDKKTDfD+Mi5vpVMSivc0q3OW8GuKSYqbVKEG+Gz9HxnmcGOrDcJkRrCulqicsKScSX5/6bWoCabWYIGTsC3KZSueEu7f7xbsyeocxHcOCtU7L5evb6lwfNaaboCWcTVtQK//aet0C70B28WMA9Wly02VeyiGD/RGYWCM7Cqhw9cn63O9UPBKpaoCza2BErOXWtOd9BYJrCahN1jzCfWhDWWquHd+SixiIg/ApExEl7LhfWDhH/yc1kc8K7hq9OlD7gzfJICamZcYrkjZRBx7LebsiA/vdOcyNxDVW7TZ8H9IaAhsuynHN+8hOIBpem1R6ASKkuJLZVzPtPr6nWvHE3Xekh2VLXKhZNd2vN630Zn1KLTKx3mieZk+Ojpa0oXplkte1QA8UDEBLVAXkhbuF9011k2Bd49V0BvMoFT4TDLVJtZ5vQODFyo0C6P3yUpxBKiIYN+DjDuGENy3jZcIQYXIodgg5b0jgVGTMS5uWJSRewUjx/UgZNmbCq6LibeowRk2JiqL4DmiKay2mkQa6BlLFyhjYwWTHddGNj3NrON+35+AN4dpdCkkCr2/kMPv5mnzgi3QJIqWUJXUHdUg3ZbQmG/yf58hLn3J1bLayAu4pSI5cMd7iDOcPx5j5+QzQSAVo5X3Oa1xmq6jiDh6/AAASkH16Hv0sASVxuE8TRWQFm88YShX/aUQcTgte0tD1b0EpuAAceN496lJMmSVM5izotMtraTUMIND3ytV+Q+nXF7PiN7N5HUD6At5Xg32nwCbQ4vF3nhQjOt5820Pem4fG82RyiZw9U3SA+uxVhaXcdV+WCG6wUh/15yTOBbdvgKt9pSm5uYioEumFQOHq76xkVgDmqmFo+4u5k+LUq/PUjYSFBiJ53/t+xu7lz3ZC4pCsqVO0cFPHust3mBOod8pBAh01dCPkD3oYfwnWBPf+MbnhO79AzA6UsP9Bfi0KOv/yLrgVXRaVMZGw2C62K+4pLxQkV0oaX4D07sVGZWTtlGn/BOFvX/MyM+17PAYd4OaEvl5gk25vy5cdm0PbYUX3DZFob/92IDZe6wXDqzc0rAIXRjCOLcabHIKGvMG3BV188kWylEKAzIJpvHKecNawEBwR2xNjR+fMAZ40sNzLD0vMxQhWgC+pQT4EiC7GgCmQBssy18L3QxWYnhjfws4CmhpeLRMk3PwCLNGw+p4xpa3v+G+mLeNlv0FABA4mYmEeOYhqSCfB+jFw4Chi5+72zUGzapammzIh/0GwNYA+WaA+q4z6atxIjj1r17hOM+jO7RGdcJjHxLcFMujfG3Vw0qpmqLO7CCVTvKxkDgMo7lTLTDhRB2nn6bYw27Sg4/SMcy00PIQ9UyIGzhoJIFDTGp+GnFCVqjbknucTfn88utRVQrKT3iOdSHV6G2r0i4byvp1nOtfK06l2mzCE4kVP5Nm2KuYSotlAGrKZPezokOOmWQSJhguOKILjeAYu6lf4MttjIF5ySTVpJ5CsWXs+bZY3pKN2KS3xY2hZtXmxM41S0cfnQJXH0ydWGsbBNLIwVhaha/boR9zi1owv6qWynnFkuASutH+VJtgoqYtge42bGIm8IiVlmfB3Z2q7kNchPgFPm7kfIALte/FLswFb6GL8hLW9O4pEG10vRWPrMkxu/5Cm0dM92QSW1njxOEYj0jHEwr37ZBVJKE2P5om2/9rjYU6CZg4MTD1ybE/t7Gquwnb9x8wm3NdsR3fhVPKOlJBh/XA7PYCDy20HtVSmvStbm0pho/HUmEVfyGQIrgbMTb6IAhumAKWb7NVkMkMhQZjbmXa0Wf0cAyZCwBLBY7AnwFuQ9niRrsjpQAeqGZWtyK2OE31WezwkpoR/X7U7IvsmnR1FvIGZAkKLIph00z7YguWain7pmC675sboI6TmC6XiI8mizzm6xi4F9tXE24+8LAF5Ff7Om4mSZgtyFVbDyTUKKIqXB8UftRmbUbf7sUnl73HsMrl1R+AB9rqOKvgQax9ip3OXwVGFcoPRMwqRlFLoFJ5TkW3FqTCrdC5mVDMAAXNvxHJiBL04K+0pyV5wZ9twfdJhZVR+OfNsUckWFf8MVuWsG7gtuzYCPSbUJjWiK6e2NtzdQTrWyOgpTUkoTqmrNofApyekFDaxJn0tjYeU3sPXMbvb9w+PA7j/l8qkplDfNiEnWRjljtOktshJHGeRYRIKpKcxWV+1iguw+czhG49VFPQRgK9xrtRjCsr5n7tAGJlO1VlJCEa2gOE6IW/Bco3YysRsVBI3dedsoFSVfs9DwTcTNIW4VqaT4MN5EtmVeA65cvfoHpiNQ6ef+ax2AVulUiXFFDmP7yDVMursb0FcXm7KIeDlFC8FRpMa91fp6nc14RrzF441OIyya4T5vbotuokwULzEP695MxWEBHhR64MIZjRScsp8oQKonpHbIec9spVDYiN1HaQW23HAq9bumrRlFiHH6nEKV3H9pXLfVsCtknfLhm9c8JyP4Dx0dFCxJB7Y3v1J6I0QOtj7wb6hrYcGl1+3cBPJyon0gk51eAspwzeHLHiuiEpuQnoNL+1fL3Z40orysvlX1cvpMol9bdmlE4XgbIXVf7KSJL3zI/FkUdoQUqLmYsVs/g5ZpQwrMz3aewxCAl5uOw6sPHhs2NYlYwrdwyGE+zUkDCyf3BssHA4/crZP47IQOnRufr7ZFa90o4IyCJ5wthw+T+c+h0VGeaNnhdRNp/TyQ5HNR4/qN9EdxO7tr1aJfF56hummn7yaTxsI5mIbmJi8uOKGTJU7RHiGIsWukchtx3HEwYBDfNbetAxcQo+1CLHmqs9tp7PF24BP6Qd7BS0nrdRz3nZJlb8cdJygLpDPj/4rh7HmB0e0EOg/2RUUUnRE0ZIZHRuJD2gXv0ZFEF3qIfgXW8XFjplaEnkihIdcnbhR9dl+ZlSB+bABD8w6q20smj/bBz1r4PaMsgnA4UIzHMLWV54yX07E11atWtmN9tiTovj1xuuqAwT3tNr0ZCcJz/2mi7DLYwAem/DKExh3hab4BtDKEWfkghoJZCJPwHQkuc1m6tABgoIs3hqQNfBKJDMINEMnpnvlD/C2ol3Mawo7EbdicIiGsc+poqrky3tLrEtZoOZ/zft6lb8pQM/mNvX6ij6oYH7lYvdtSASOmlkqtuSKyWRxlAASZVociul3HU1q9Xt68iDOvls+aFS+Op14OcvKzqpOTbW/6gZizQkohhXlujGKecvQ+V+WAnLEDgk0W2cA0Mlqt9A1A0HPHt/CND4J2LJm4AulxA+sfXYEmSv861YyYq9VaD0tq6p1LVpwQ3cm5HjWcv1idt8807Z1L2Id7ER/N7uOUS7L0k2UniL7P6QC4IEJW4JVHvQJaO/7Xc7DeUIkv1SiBiGVzrardAiMAI6hSafaWZwAvwsn5GfU5Ng9Uz6JoGf+I1rHgZwb6PP9YAkFUXlFFBqX6CQQt+9axTPKKd/AZ9w6IHHIRIXwjRnLupSoiV7JvgrpQNcQoY0LHxAF3lTlBd91gKvbwWAYTiv0QdBTgJTV9Uuc4Zdp9R9vNTtfs6OpInFvQc0bmKZXoTF9P6+iUetATQfRshlgx4BjtfK9khPcDSsCG9336Lptz40AUh4nmPzxXNZKI+nTfkGoGCIfqVvoUxwlgzFVyngSIll0RlNPMaejUabKI2uvLdBDmnVZLtvK6fW1OxjXHhhSdWwFjxv+favZ2y+suXte26AmFOIuyv2Rm6L9ir76htUVDmawHsczq4PJUZG4OtD8D4JKgGzX7Vg9n8EZGBGykh29VRFkV1oHR3DYTHuldeBQ3z/lyBRB8t39OWaqRQ7IrLD/0ZyLn1bB2ZvtTo6MvW6yLb/ckvkMvQXe9noPrpbHHnEHWnrrCtbVeWWOsMVBYjUgFKLJzeRxYUk+vibIKEz3a4/fTxll10kOIsOjIp+x/dchyU+lezTz0W2esT9pfc5mnIachMdOYDqlP31+OUrIYYX89P2cd/u+mDIPf4F5hR61WWUI4dKHEp+fRgRCOrUk84LW7kezK3W0B7ri1r25kF/2k7gwkEVBL21zmLXYXNFCMCBJCMc3iVDvKYCktLPUOyCheO63oRVbGCgL4LgDKP3gObuwT9xTUDZ+L/cjdbykPSbOBQdrCTWM81gq1n13ehk/T1jPoepjUGMToGvfbBfhAtXvDpgs1ly36iHB7ZxZCG/6n5PgFzjk4szJqH7QfHijwW9sJ3t388W/npXzXYu56ESyau3yVwRhKJ7xqT/E7woImUiwkRE4kwg4tk3eQp415DIsAgkSCyNqTooX9T2udnd+708V8Nwl/B4zXLGzOJQG8QrVfiuYEqRLReD057NhtQ/D/T2U7KGLAM8cWMC0JeVQgn+/tS0CcEhxWwBmVwIp7zLbkWqezjc35Z7mcRepBKS1Db1iTdM7YQdlkj+XP8me5+SHNzzCdfhpNvKMSsvFAFiIJeUU087OD/wEnMh3V6Ki8NXl5sYeVWm4qi09QNYPFgl0z/3eU4K0k3i9lOsGUuBSm6wP+0YTT2ppve5AmA6ioi+d1dbPZLnVAISA+LT8ObdTeW6T0wYbwM4bg/qQ6dOzsKfDpLmyfcYWmNS2FArFhua1s66ZIXGObc1IcvwdHU6gPWdFnkWGSTk7DwNJUyQXooUrNkYL+x8tx14/kOznj4nFBfaT9KQiiMNZVNbSb7I7HjynQG5I1rnPr52Q+yhJOXPMoEaRwDpe4pi0zTMNNEZMmcFWLa8KQi1A4wkCerMyvQhgf1WyJqOX9O36SaJZZxEdG13f3+PvtJNFvMn6iJKnJ1JuyadrAnOVwx/KaNbyNy0DuVmzeh0maLdTIy1yY3d1a77XlcNIZDAC6dAS4V3pVYogzBBRD6FP9kyMpQK22LJcijv2JCyS92gCJbAiR2wRCOYf1jImPbeDOFLCGK2DDLihrdSWMPXzx46qJ38IF0UuGxosv0tL7iZt4TrOXZQXtckkMCNZpLYgH65d4PXF9s4NRA00KmfLdh0z9ihpggvqjkXWQCMsef5c8jBivY/+e+xx1XY+7pf5zBbqi6+MmGvkRnhbmLhOcyJ/bqnVfXcLcrmMUoZtMk6m6yD6kLYau8zhrwR3ZdIQwQ7N3WfMbIo8hd2FekMVIDz4cVfzGtEkQSPIIjmJeUMZ2TsfM9jyzXkUMPKetiALE7UtWxfQ6eEYPOWLNjzbh0sGp+EUoB+6OvP/1RZzDvAncgz/nWjIAS8H2S4LrQTO34s5LGGZmDLRl9f/fVVrwfiWBAeiD0kBXSYTNeJW4wULnzSWlvYr3ll9lCaWdQOnS14yJFEW05VafnYQ3UM+tlbJlFozQ1zehZxNc2Pv3KF4yFp0r8o0fYtMkMnvA8Xh9dmvJ8A/tt7GImE7fvCZKxANwej9Raaf0eCwLZfdW3lS7FB+CZ9y48kXntYMU9JxFUnqoVQrF+hVMBjMRR0abCVXfOVAwbxvdAxIrY8qV+jVGa90WvhAkKkgh+Hf8yCiri6+ifiMfDnv+k1W0UAwQj0dLPop8z3y09Pn8A9G80BEPFmI91s9HJBsAPXccTYveHQktvoUk7Qq+W8b0dAsjsQFs8BcTvGwvQFCYvLo22JMgHL54hZvcvvC1M6sc8uDfzPiQAj6orQhe60GhvE+35362Atxb/fCtBAaKGebYAAMRFg+wsfAH4aEzHvhSFVl42JGPakQS7s2bTx0cbVnMLsBSSji47jIXqAXtiduTFP36loKpYOl7n3KmR7bLcewC7AeNctVIIQ+0JeM+5FjJEQ1EgYA/Ax7GmC+hdXezes3eKI1c6dMOjX6/3lF00DjU4+AvhBkrR3M3ZJAWqr9pSB9fy8vmQRanQxj0Eln4SKNu8IaZ4WbqlEEmbOFJ6u4Io0RSvKzklYMzlm38bNqqEckKRNGspPs7uqYvFfqG2HmzKtzJVJuKvj5zInVSXD98FHeTFA4Eg2qwYhb2H76Pqdb9GFOMODMHna5A7uU7jrSMKTK0goNnv7UZAPSYdWdAEE0E4kHh/F1Jo3J3tOfqXI4ELr9skT6zKbOl6YDbPFDMgUF0IhgO9zQhKrNTf78qxC1KK+lA8KRdFFQb+PWgT72S+ME8dufBZYKNvbhX/QlkgrDm2qmwIU50VKz8MCXCQnYEmjp6jiyqd1FmZyyMg9N0AXgHaPAQwzWAmB/G/YJOGjmk7g1+eu/m1GCOljgkooweAOnryPDQEBmgcG9T1ps5P6ps+Ya6uiU7TdbZYgAZVI6oxeFIPYeGtMqCiMkwDcmWEfYlp16lFc4lVrhpE3wMtXl8/h3UsrNcY4jHEnsWf5L7wV3ukaj722ZjoQOkGAFIRiMyY8F0CshW44gtLgWetKFAlJ9ISdV6GOFb91ONxkUbRHNoWthbRayDDBOixZIi/5w9LMwGSfxfCyzYlnGgBvxxZS/POsYb9WjAVOgYqj1+gA65EpkINO5PzzG35AF+ti3s4QqSQWtuW6ZW3Ry6uThtt/Tw0EDlFDUIXd5K/o3/U6EYl94tslMYDc+AIoEWRTkqTsbsm6ZlJwQ7ARR6pJNWX9/7NbE9VjDXFhhVJwnKWCg9dTi5ifCRMW9eH0ek0hg8fwYi8daC3JoJHxhyo1nWT1HdxY7Q+UxdvBh84hlvXvwD/pA8mD9/NYSVJ2n1O0PVGMC6oQuA2SFQ19/+z04TkDQEi1x4uI3PvE7w3kRn3kfev7JrSJ7508vfEPT3MylzWYGnNNjlstjJpkubu5BRDzKC+nZwylJhJUhrhGCH+SfNH25r59CTULN9buN3C9ZB7Ea+gsFvnZ1TeRDY5tzP5u4RzCkrUlC9uhhd/y2BXjMzZD1xwL3FCXMECHccdnKFfpjbUrhqVFJ3RubK1osuMzNHQ6WR7Dy11GLbvEXA0F84yos72fYJQxYgjUb7w97j50wmnnL8DXDXrQzFxX8Ahwa6PtHwRH8FyCcnvqmH92eCU6JUf92bp3O8J8WKGBO+pfvcFSCpvtZhRpvbMlaus5d3Or7b5YmFqk8ROVqDqFPIEhb6dyDQsdzrs/N+X0hwLCg9cDxpb5r7JOg24OBgqtQOPsOCK6rMj/b7dmPIbmaI2su0QMeNCO0wUpim2/7GiVNgmq3I2Jlwg6ZlhZyz03TiGygZc3nLzdH75C0zPglSVXojAWCJps2cIHUozW/0ivvt22v9+WwcHMnMUfj1GGWs69rtru7urW3Xz0bcX5sAkftMgsB05YdWZJhZkMiCldJMkGfvhUo61x2DRig0p9+WhKv0TUTqABK+WAbT4yjgJUS3dTGFpOGqmWZZRVD6xXEFCsRg0mSDubYcSU2YoPE4k0676dXLj7L75BGaAskadGF7n2eAxJ286S28xa9vm4yVZDYlTZae8eI+3pFTCbFevS5J0kGdZ0TSzy1NclOpOPt7vnT3LzBEYjxjILS6xFmg5+WXnGyAW8YDip0bSslLGkRd7SaolhkcCDz6r0s7gZjFtQbqdScI4odDP1JEweS7TSw+40K71Au698JTMvI8WnIcowhu2blG2b/kOQfGGlaUUNZoVnWNw1IofA8mCYAPSNwPhMsKyBPaKPvY5KAgCAIfHBnyJyXwOXRQs9Sdld6+LtQcuIBv/zeHlF6w3xZxlGbiC6G7Hb2Wo2TJfUJ4tACJnONM8BpETTzFtptGgNipolfvjb1+vNsWAByCkv60yOBlFQcAUzVu0ZZzSGNTSYEqgd5gYtqRNOjXpAIZTxw77wIkfH319Ud1LdZmh29ynRBprzEWjUOi66Q1dRoLIDK7pVsItHaDTmvv4ZnSQNhYqyifgnpqZLRzG84/vlPwipBkOlO4L+r1zpZvvqY92xyhoPnL+ODrrFvaKqI4aHdJBIQdMGJecD9t28ZLhkGuUG2QNpIp74uD8eJUu4qAB8FapCHd+kbaQnXlH6MzzinR7wrcgWB2ONA3E8vPjzmZhiaqi7ZFfm8M8AdVWOdxZYhzBWtK+/CiL/7AO9cOQx7tzl8BNb0hK51P6PZrfnitbvLw6FIRv9x5Wdr3eITxCLOm4hjKr+yKGSG+wilmAejJw5I+eFZSNQ5vYrITiICkpFodOC8V5F5EqeosnDvQIcSs5OeR2AC8bPxWjB6xi39ET96Txz7UUC/NxihI0SZBMmVd4S0ks/kb0RDR85/T2bnlGsRfaxa1LYBKkjGMgw0SwWAuqRoJltDK5RIFKEFdlh5tSmsA1Or8T+PDd59CfOee3S7N2twMQLZnTyZMafxdcmP67y4oPZezP7Bnt+wNqF134fyckNDfmXkBRucAW/OuhZS0NkA+3nOdCBq11LlDoTWgy1OW2ljr9/HbAv4VqJJ0YmqdOjBc3mEP7kOcB56VkzZG4TbgUBxSFn4YzDMDI26MAik4zLCiJHTUKonEQ9tvp62qqO1nXIt7zV3l/4cyzyhTQlcFkXV8PjKBYH4qTUz6Nbxao3h6J+WmfKTZ+IvYGl4VxKteJJTpPSv+QWNgqqgVavZW8XsHZzukUB5IRZ7/H4Df7ABQxoj0LzBzE/75ePugTJuzKFQaVHn43L+NVo0ccFQkC9kTiNg/vzAhRVtslEXSKwneKpm1pIeZWNdZhccTrQ9gLciXENj/W2H3GfvMv1vHIoeBKqaOSOgrx9ThjiQuKex3s1U/lBBC2ke1euyeRJ8M8K30fbY9I71fAAIYV6CDK+FZIWroAss2pHFYpkIfIyZCdc0LV5X9xUrLVHCLx842ip9FbyCj+jw8zr8AqG2Ad/1H1veTeRDo81gktDHY/1cLWgncmuueupisWDTjod7wbnFF73prWdsWJbBh2FyKAsupPUIi04tiV5Xi9LZynAf6Aejt6IP1vKpqkqg0mgIXPWx11JD3Ck39iPElppAzPlUklgCH5CtoacG7KTzrVJD60VLALKPCaJGXoX0vBl4z0sNzbx3JWrW2bZPLRez4J4EK15PpJ/5TmsuTQy28NivG9ljUB2KMQXO9WcDdvZ1/VqFaBb/OwhtDdHPkQAFOYe7uW/fgTeTFgHx/NCnzEMzx7B79UHiabsHDdBAxTNLophWX+5tUfY7qxLweL9hxSq4+hVt5/QUzKmhVvz4UD2Lx1FRAJS1EOdUrSmmso6Q7jklo0e7sGZEwKSxUEF2KCXXb0r8qTjUExpQqdONtE/aU28jpqehsHk7XRhPE2dYPS03q/Gm+T85nLBc2cyQ0TYYx2Ejj4GqXeNjXkWc3mZ192ZsOxyh3ucq/9d3JvR+SzMdS4HKPyju0YbeK+mX+NFm6bnrRakiOM9nZsEUs8c2SPX+70lMzaPBEWNpfFrBVPtWxqRSSpT6Jce4C7L5jJeGfT1+lCSooYRKNgsNeifaQDgPs1vb/Mu3xRMP1ZvqSKtFRYm50eguxyYzvg/VeWunsvTn7csVEAUQEfRj1dcLokLmWk0gYX4fN6ftixM255HXKIHjfx23S+lW1gGSz7SAVuR86ew7fmwDY6u1R2vqRBEM9g2Ualy96gx6GZbgQ2v5/y6/aGLCTAWSNwZaUHNihS0KggKyqQP6fK2PZbaCiiKmzWbhsGjOVoRM9j/VFlyHdgFYoGIoRjfU19PCjZhnCmm7Lk8XhReADCMZXrUvlvNbe0JCzGPGoYTn0HFVVCoXM/7LxASiRghqIjmF4OWqLVFTQ3sc1pBbRo5BsDcJFIKf7G4laq5a8EpMO6jKX0/rXx2RJKUIaRlHGUkSPX48tuOsFNrpgwozw/TE+xSl03ZU+vLHctHLwXEcojbuB9PAt4K+CSZu/zzbYsA86LUH9p+tc4Xzgn6bX8Ztl+iT1zmrGKh/RWDjZ2tJiLPEThKC+ihW+D2AXn/I0SLTFmddJhnc+TLBlPUJl1G4q+F62bhYZH3aJJx5YiOllGpu+/C9GsjN/D+b0pT6V20p0F6sb2bwhhxl9aV+yoL+O4zJIO9FQv+HI6nz3qXdSZt/lZVltoYmw/mCKmyA0Ka140Y1WH4gTTG7nU+Q1FM/gIxRy3ncptjOYZvQfLhYoFv7Avt6o5zzxHoti9VqMt9j410SHYVKQefZMCnY57FmI0yE0bt56TwrXs2IUUFQ83P9kmjP4/AAgjeC8chzIR6x08UjsUvv1z+PMD490ZDWEI6ThAWTAlJB0xMWzL49F25B6HTtdwj3EsByLbjiZnXwhB0wnoiC408/ho1QEpk2QkrtOkiAf3kKJqgHjRtv4UQ6WwhoqkAq7xLRlTKtvtfm87JM0xQJ3XT/72BaS0fdusbwFPXolosfpeHFLqtDMsWPYb7QVDJI6+wtB7DG4FSlRfqQXCH5IkKnlZxTgap2Qd1EFG9cHkivPVMNgdhaKX5Ek30p+65qzPwrQsRtpMjk1bjqL5sH5yZMIF10GJIgajMshf5qx6SlMAdjB5o3t9HK0oZCfBk10eEXXlCXhOCyMYjtQFl/dk7OwJU1oR3olm168FhFz0DPGiyuoLYZ5ZZYVJTh8YShowibINrW+uyztaFNCnVC2orjpOMEnEUeQw0JD7LkQwG5XLYBRXZugCSZm4Qftmpq4FBPgXGjqEmriNDK3chpxHADXSdYnW5NmEp82CvWti+YU1wCyGWA2MEHu7wE7lIiF6wLKBvIs479hJrOISPOQpl0p1SoE7rIOmGmVFMhBljW/l+/d0oTWVcGYkltEPHoScYsdDBgN+sHWnjkat1Z1yNkqOA/U7J3dPfL9vM8NSbiz7vCOnRgcNtjJitxkbYZGXy4WbbCwFFP30v6+fc9tPM99l5Nz2z4EfHwcQnUv91eNXox3LsnzaW3fSED/PhetXI3hkU0kWkPezG4ZkuIdriEuhuHiKjgDTmBQWXno9TDxkQj/aUql09QJa5N1UPmce53Y5uXqanGG4SGyQ9s+epdT5Vigc6Q1lC+i6ZeBTlij3vT4575jFkIqv8d/1X/XWoBEgtqrZP6eLSaYLo+r3Wr87hzRP39q05HUQ3fkt+00HmT9QC7h2rEMxR5ZWt1pGJSgcPZqcVgvsxPUTxtxqom+uv5Z6gODyOjG5CSlQY0ALfBz6JsPhAE/q+YTsCtTSMmz6Uy0R/Coyoeht4nqagfm/FoqfC7dG9qtc+FY3LTC2r3mjNHS6ar4QIynNPF1j9S1HQAqhJDBqcXRk0iH9XTlXq/0p8AkdDhQ35Eb421xJpgcVkTgBAl8fn7ZwDhc7zy4QXVXitL2x2wDhbbEfLvUKO0DsfA3pq/uCQJc+FiUGKWuVyItZHmSFmrPXHsO2xc/X5l35qbJIM+4iyfCizhRmufFsQwoA/kIyp4+nVNmtQXZ3J1P+NAaEFf6u046uNTxVxwVFEkaAkYPhGGI0aWnxId62Z3nJFDgwg+E9AlW1iWAvJewOIPwqSrfl59ZWxProiUO0htNns68hZCiDI466Phqw3p6GsAZ+8vHk+4EIHpmXm6QiqY+OrGHFB9d0YWBEGOvWfoBi2Ly0Hy2ftH4NoxTYJJx3TgmtgvG22xBaLAzd206yBcV2rfs72Q60U4LKl2nRojE5LnUXJNNDBfGp1RjaTmtPyGwMJk4WhMZilTf8mrjktyde404TJGSP2mtMchTyMdJFfZvqpMrfnfMsuQw1sYVfJPa9aij/dGVaxMqrGJxdPVxIeuYVMofV3hweFVrAZWJVdu5SrrRRbAAgF1mnAcrZ8qjOcftMA5VuCupRV81hZLIryA9Wmw9RcXumv9NR1LqGCQjc9l/OP+a5n85XkUxGY4YqdVQE5Fn9y7KHU3o5REsgBxf9spOWTo0BiX8Z7QjDNcKlIbFbJCGVwtRLZyIUpuGknCjh/fzQqpaJQT37pCFmmAtmULb0Nnj6bnGxLjs68r1y5UWadqmIRbB5HZ7oljRYo1bXKOMKRtgwYXS9LFEppyQzwbiR974QZWRqdIEs9wfx6nQLashFS6tG14v5s3FV/fTFmnczwwOq6sJb+4ZGYDJtYVPwSWtYJvEWaG3fGUz4GdeZPajnoULvy8QQnlCCqT8Bkmxsp8zpGwzoNbBGsw7NfU+1HvOm/KVkn/rVbeejpKvx+QfqzvtUsoi3atH3eowS+DZ5GcPfQfSSgREqv4GntJt4Kp3jd3Wjn7mTBYXF2sAJKTROvumsBiEkZu2EIsA38Fc3Ui2GwELKHoSAyp+0JY7rWJB1TQ3yxcOqKlkpZNIWQBfg7mgLfrmHeJ09fQMRomFjfHTXDQ/X6C3oyUwWiPeFNh6ePrS81SP5FzlomMahrmEbirk6yIggnI8TZZsXOvMvs2IdwFV0wFr86Vw1Z7az+dg9X6SAm29aCCK/JsBTN6NF8g3FekeUGYZFIQ/0Q6BMGhCKSFFBxW3AkhZE0Rj4IarQG7Wpnss/As/IPYOq6LyZVpAAKg9R1ihA5xN9Rxv62yoh6StTU3YoG40rvyVUm1jvmR6d8maXUMN8H2RwbA2zrVVhy0ZDqxIIi7zloZVE7TmjiSht2Fz+zVb2+5uUvoB3EnmzCIAtmYPDYtWBuRL8ymFbPX0GmEjNGEnokfOdKcUiI51QTmrLUnp0rf4r91ispSQjeRi15vBCff5qf2zZNVHjfjZQBidMAauaXpijbhdnj59faJnyrfWITXhGFcQiwqYbgfc7NRAKbUYklqOtXMb2n3L/oiCgJuY94RwyWOlY4w5McWksQTppOPG2jME+/pyljRUNIWHMmOVJaf/ysT6suX1kYEZRgQp7KR0yAsE+iQFaEjYY7FlmSsYxSYlNzElzA7gs4eQ7x6tCBB2pbxss03SJl56Eq7rFOsBfGlWMsN/8afazppu5MS0oJTKvcGshtzJhfRqbfxoemD/a1KK4KE2jb0TUnA7yeVCLJcUB4DLAUC3nxhusw3K5TdBOV+Cm5s1+YTuGPncGlzjd0UREp6UNtzWBWN9DdFKHfwqUv8+TGysrlxBFYXCefqXqDfePM1/Bw4fPLeiKaHaJoQOt5LJMZxUGYuBlXAmOxGhDIBrOdN/GKOgo/kIM5Qo2HS25WmIZ3Wcn9EimR07RUXBxEs+I7J7Nw1uBvpzjGtItCNrZXCxf9Am4OEvzKYarWW4DUdLWqzUWEjfxaGdkFo0KRzYH7aHi5paFIjned2xSh7xs7AIknGVNj008ao/hdwrgEOWNXixJtjnYVYTWhxKxcdxyBzehvUtl5nohfhpBzPqRwg7DVRr+mGtj6zI8Db9F03oaGi+vBgg6UHs3SWEcCJ+impg/QGlKERraKegmgdc0oe/HEbOjvly6uMWRUoKjkbZGpnDmuuOFKwLBBSTV2GIvbgLpOP3kgbChkTRgBJXvbqo9e5rmlEfRCA/qJLjHN/qYkSdZfXPG6FL4WswFMQQJfvmrb4aweoVjdUjWDcY9oJeIJIPbRcxOMKwODZ/EmV1gCJxwvjNd9lH2ZRjNRuctdnOh1CFuj3xWAbz80cmF9VfgoDfM/3eLF881BqEu7CqCzsmEc0zvId/Hoaw7+d1WoIVnnZFMqLYiHxyRLrokfFDl4gVP0VA+f8ibJdOxkH7yfFL1pPEE4/g4zTrCLjVoipRKlRgNtrIHMPO9YVP8bKRqUXfZYvVnEvAeJwSewWNY06x2jVaiXp+R+q8wutKccXdsQR+TdzKKRBKKEtVIlRPI9/q7lUt85SNYj16kxxOWd0JusMpkGJOz7ji3SD2z2KwSRSIfOhc0tQFb0+6d39ymPg6ZXLOFRtt2FXxLoVCCpG6fD+mzD6ciln0PbMuG0T60Ak9Q5fFy5N5YquQoMf9r50XJ6EDhBMudNVHXSc3a0ihAvJni77q18MCtKKwSxk0V4SHyKR9WTQQ9IYleFG+MxZ/vUT1G+F008jQW2fo0y38YMDlN0EuXsXGalBDZf3Yrtb1ONBjLoGNiDj5rK6L/w/mN6XTwqyx+Ya5U2GmLMQtnsraE9OjDCPciksyyWr2jzYIcE01m4omTJVX7tdtpMbnus5ibBFDboryjPK8wejiv3RP7aUuHIFg19r7wHqkUIb9XPKBfAKnMyRD3965yewX4ZGgQJ0It8bjWaRVQmhNao4v6or2A1wLyIm5SGEzkXZUu/g7yCEhxPov5d4lBM/IGPHVI7c+tr5c8ABK1XqX+nFdSFyVSaLF6juDWqkyEPYmil/gsMFYUf0hTy4mRK2wK9I7Zj5rmpJN1a8PKrg9N2Q0jskrogtFO+3qafrCEy7LpPI6/I6kSwhGNVQh2tr0inHRw7PgbKY0Wq6ySPcTv/And0ArWq/fxJPngfosoRzdgbmkt3NHzw35SIXZjb6bYyGrXkNA9KS9axVNkiWOODA2yEEwKxrbd7UAVDAzGZOROnFc6zsLHV5HNo0Bx8h8w+Bw8uje8fAyF3JsWzuSXb1yZESI3W6eTLzpovZABB1LUQ5e/7oV+f78p6isaCUOHQRrdSFuvNGUrX6NaHfzfngyafHtokm+WmDoYXlqyeweYD8gQlvRd+q7JJZhFGwrrai0y93w0RLKMQXX40+Pe0WSKtIyoiP0TnDCvuf4WKzGIK+r4QE4BcmXLO30g/anlURkFY0BT6dpB6L4KHgngD32Z2N4UptS1G9g6fC5EShjGv7SiPgoE1v8rrnrLpphaAGvtO1VPowvBdPEUsAI6jzAv66Fm2F25ZATwUMm6N8zy/42lWISydAOxhmaUxCNaow2cSntwWRFeEy29cFbeG6y4hgMgGGWY7tAg3xZcYFgEV4k0XPx3QG6ogUdty5qLGD1wNbtkTHjN/bHZM4axMZCVH2pqruKLtZUE4OtKMho0f9K5fXMnvpnZAH0/Q9DEoflsAaqcGTxL0JcO2lvNEZWHb54m/JpwDrKxQHVLrJ+Arvw1S+TZp795Cqou8SvyKEJ1iY6qOwa26d8h5IMQmGejTRZnr4rp7zbbmyhC0swljYd5ACkuZdyjmtmC6QdrrmK4DH90kUEwov5jJgdYEroiCiQXEsGZ+giYEOeM3oAdmU7r0tx4ljcZ92PQwR97hV9ICAbCaVV7Jn09Qq8oa09FCdsLJ1v3mgyReYhzVNrqJK7vSSZzKS9dPuBqoVyqk7/cH+Qon17hgWuTSz/N6dX2bbOYxAWJ5EVci9y4s29cclYBQqeq69saS4SeSqEbCMfCedhyZkwaCCXczV7qJeiwMb0ow6CAU2Hx7AQaDbiwGzK8mnnGpWn7lJQ2VVGn1QQRz8+ffpHDj2v35ziPMbxlfJEcqnBjVlns6MnBEPC1ZqmAvvz9Ec+EzGOi55nMP4KR8CM/EBVEYVrDATJtqjtrkV3TuTZg9huTfrBoC1l7kdwIzJ80cAkhm+HnB/MwFwNguxAfSIkbv/vHRo8ReiMOUzGIe1+K8bRygvT9KhVwfWTLU/atlZgA2tANnw6kJHJxBAqJF87Slcn49t0ZZ7xXOT/LqbZ6kv0y+o/vnmDfjqKMrAiftl5EGNY18RY3P7forhR9ZIMMK8pjFyJyfOW8BbsTh8FtzJvP7/JFPb+dkD1/7lvL3OXVp+OLbDwAB6W6+5lFA4wy8PRYlZafepKf4YW/pXMflKjQAC7TOyVyYFmudGSmJRW2sSJR1CQxqbZxIHor0QJo3YeyqdscaBNGpi9M9lRSMw3Vx6Pbly9Dj+6tTqRsnmKZRZ8XE3HjaEiOmkU0bvKH2BE382uvQj7vWCcHzSOpsE4/R81It2KzizfmSGwTs4MikPF9AQHRkt8kcfeoCXhQKdd6iIWnOtXAngEYy9Q+Xzs+bZkr85Y7nYq6vfgSDKVYJzG/zmUJL8yZVl08p85ZWgvj8wyupegXez6PCmPdDHOVkOcywmNwFtxjxmVP4QU9IKX9/D9W6CpMRUeBSRKMjWuTmjcI3pLQgOIHDMQ4PDZ6wV9cDlxWLIFJXbFPDNtjqMADR9FV5XOCqrih4jZJ46p/qw+t3SoMsoNJ2LplJOfzReKR+IwKAylNMbp5t6evIOYpk9QBF9/2fdL2AQvJ6CPJEuWQcIEhObcyrzSWnklQtHzwwQ/+Og4B+LsEt0DD9Qut4DUFmRxV6lmMZqIGuuRgXJCltxfg7HAcivqjC0BVp8UM6X8beJULLBioKidpAKmDWiH5E5OwA24YMroHUOl2C/XmbysKlmvhgZiSsnGMaMe8HGXrwSZ9ojz/B+kkO05zvZl/Qp0YMwvExdOjaftz1r+fLvO+F/HXjpKnS7t3C62dWY1ALera7xF0+LIgssOiJhOJH1WRtXBZjXi66xQ25qk1GN6pn+Zr06gmCNzJ7MVeog8tvC3R4iTQUW5TiN0jJCIMMH2iSzsbM8KplqaB1LBO7K9rv043QQu2UItzQFo04PcJvaMQBkOmYeeK5GXgsIqtKiyOwEmejnz5TY1fRxXpV+/EEasiUWci0C2N/jxE0wqzM+/p7fbxThNBLIH2RyTIMExccDDxv2G2mHdzutK/QPQGkS2te27HST/WlaebpBMHLIXUK1BJAawBax23aYG0ZX0tVe8Pu0TIvCUUspeke5f63IDwIFI5fXgJgwFnfr/TGcFabADGuhG7G2r6ojqOExc0kBn4096alxGgB9uuxf4GWedpksXPoShp3gttdCK3OMPqHFdRIgEvWhhmmOvt/g1Tc4PYaUnQU7w3QRhtZuOFtrKoio3I1StNwC8WfQ6Q8lFpfIiJGONPN8SJqd8OMM8DWENBU+n8fpAvMri+PWdFplnsnDenWiywpW4Jr8wDOLNS3OeehccVjPmgp2CFNH3l+Y7KOGgOdawXtF8vuMax2KiDsMS4U1QOYTMv6r8iW3DFwfg3gZyNFqs0rP3hzngl5Lcy3vn4pZc1IaIRKw39IOzllfUywGA/5QFX2dcxPhCTwqxX+icQHm9cIdvqe6oNy2QDmAgX5W7gagulonRpaApQIeSTmvPl2i36dWqnQDeTceeeqmdPWqqUh5Py+HgJJzYWc98QNhF+Ll+g+rfs4aKVQLVxjheTDxrsH0JTv35SPv0+5nN+6LmmAkXr79g4QVWr3+zxV61LrObveSeVWD+7OVk1kkYZr8bI6yPcQt0haSxYYVRlqYMpzyw8n8L9RyawKTa+lkYjZZjCWtzRD4TanAY21hpVAOIwOhBXHlsig9HJ/KcT6s0ezAvgzEAqCHD4qQI4cK9BN8gwzWk5eFOmUx+3mTd3j8xYLX8xXe22pxQhxOBkrhtdpTgnaw7MR1t8spphsFvjqQr+K/AmKJy1EFPFXfJWtvNnJhNOB2K5KVLF6MFEwK6Xb2XpjQMAHdwjDhKFN5dZfOG6OCCv5X/NlGlEyRi0rH6lyqpqy11r4V2g4pdpFOcqKbReDgyJifCPmZziMK5AIXQMl2/P8EiCRb1QKLx83DuIx2tj+N58u/ZIzBiTkzCnHfANPwe1lOkQJRWq9gDUk34Ba7FA8buT8YZZ04ZNgq9lXlBYrL1zwTFm8gWC1SbpKS09SaBa96qQ6DID3XyWPdTBv84WbPKz4V/ky3hS5rhEa38s83EuEGZ8Bs9DLfJkQOV12XEyQYLOUbEyu5m4+H/8VO98piII1PSqmdGZvAx56x0DH8yTfTFuI421grtEqAmvR30WCsOfUw0HPUDFdmb18JoktQmeLBFEge1RIn1mRMQafaIksW2CM1CdiyY7Y/an/NX93EY9fZC4Zgc/CP2UVg+ypStInvgbdPd+h7EW8+JTCgRuNxf+o9ktJ19Z4mUmgJV3JFfhClo+2DoOoftifQFab9yFecSYocX+Lp2tNiCJlJmpmQE/p2dLTo3/ncwU5l3/cA/gzRVp4565tUiYo3owEK/U3a0Ht6/Bbju786eJ730KohblBaNaBfaaX1OTwEa0X5hvV/lDoGXi4IpLW+rsyA8/UaaOtAdnDFIqqYBxlQN3SRLXEUEzjzQtJYwDedEX8nSdnb6ddgFdXhMuJHutwl9fRTQEI623BbCC7PqT/Z9nqYZyFd2lO7Sw7kvMGT37DLwKGHQX9mh++Ye5qMhBCDGGPyti5KUNAXXsuxLRjT0B4V6gNYldeY8c2wypf3gaoOWwwNpEm2p8iua1/T4WZUVLlyPLJKzlFMBRp067ydeY4ltR3IqP0B8hJSBZP/0Bxoe680/XkoWpomt6KVxHB0gmTpuCRl9kBWLzle/UzA7CSMXByAnoslmaOQqZAy2Mpsqpmg9INGhqIUvLZUnfG/ENbuS7szyBw8kbi8J/6jKN4ZC+oHed27EhWRqMO4NxCKWeTjwTTjon9jVExXJbDkhVhi66Z6TcD97jTmiF66S0yF5VOZPX61Um0XZSagzg2ddcs+pfd/RqACb0DK17KJg+kf9AkCoZGLiXGxn0g+9qqxR4tNes5ZKPRA76l9btkXjveHKKAQPvmWaDY55R3kXgxHxeWJCUKwytVvLWTVEUAYtMRYtPZ9S7EKQmI/Yvx0pdWeohGLSX6ai+HR3XyMXGqaJK4YSq9hkSE9lGzTTWiQ0wKbAY1MRLQ6UpAb6wDFf5hEljxGMM2sXPjrHaXixkZLctKs8MSsDjcFH344F1gvp7i2ya+WOjdwGVDwHJNHiFobPzrmvi8ukAz4V4+u0XE7EVBWl8nq4ChG8O0NsauVPwzmICpK3nUvjtpfEgnJpROw1gVZqPGOKXgIW64BzfswsJc6f6EQcsqX6O5fP/u1nGM0OHD6Zg7Bz+RHjN7L2bG+DKzX4CqBnDKs7RODLmdldexCQGleoj9o/Kdcx9ghnyi7/t4KmrHFKIjWdSWdZKaSnhZbCDJeGlqhs++/RuxLHRLKx+NCBPW6jwprsc0f9HQsQJJOnhRbt+zDcC2SdE6C+HRUdW3GSikfuYyh44le7CbO47BG9PKBHYoL25e96Vpe3ljJPcc89vyUqAYsfDubW1BUUEE/algOv7+PQOG8QwH/ttHv2eaNkNZ1oTIUPznSteLrQd6fTJX3ULqC+fpTc2PyvcQq29Vu3hVVXfBneqFvxCmi3rwn8BGFZnFiAIAon3qm5/WNBsItzeYQ7dggCFBk5sI2D8youGWxEwrr4+UEP/P+ee/W/k/T07Oj0AHhlJY5uQaEKgNnOBmfXpNTtM4yhZ1yuVVh3bubf7o2PbqWFebuvtk7r12WuL83kqWN+VOmCyldgtgPUA8wt2KleGQcFjtaQNXjCSSjOoe5A4GqFCm43wCtP3a/9aX7bk1pyXoVIYEf7kJhmtCL8ZthV3MXw5zMSQCeRgLTwJh3/el/H8pW13v3gVX3kgILp92uJi92iMkb3LIvtsKM3WDMBhRZ3o8MW10g1DxIgDKxwl21Sw8lJZQ3T5AFzp8X0dfq2UqFbCL4Wdmskh1t8RTZ8HJcjHYI8oDlLcfl+u4SS9OVLG9+nJgHCT2+ei1VYsBqQOsOnFRLd0Agmf4X6eorn5x7X2DM3bT9/dI3YEp2u0Ys4r5XWrZDHZ4eRDdGXn60PdmEPeu68FRDkW7Qh+roObW1ONtakxyuW+O9+NGwb+Q1iYR+by44LzBtPL6kELiVSDhWTWLYn/DH5AuhS930E1y2sILHtYmikeomhZb0MGfC2MuwdtSE7DDPRPZtZ5YJVw0cqgPxT2O5agPBxpzkc7eamnIsSRjWCeE5Vq+h1LYgE9NtY6d5ZRjLr+mVxp1Ar3v8+aRqGzjYhfEKgJaWmGI/PDuWYr2wD8P5IeNUn/Bl2YZclMesZpS9YftEp729sSOBH34THyeXavr1zu4cXQlfAln1B5aLgU/I/I7ig0Bwo0h7XxnFa2SxQkjy3WzmBRwXXqyfZh9WKd4rLUc2sKvsaeY1Jg6stWX4mX5MgYaF3DjolxK9v7cAml/SDxxCZYyO6SHMxif/EnL5pJPWdrXeS/e5wXbYkDi7E068/dDxdNb2p7rpQRMRTNPSQDlNL5UzaKD9Z51f2l0ZFSCAayxUl/6Mvh407TSaw3RsdnxkCAykhFfn4pq/4azyut0zf03RlfuGJI+SYWg6jvNSdyyrUllFsPxqB1tRDBKDAmvaLWKKB/1b5AgAgLa0fZcPtPbl5G9T02pGozcU7I0nSTBvIYxDvy1x8Soit9dTgFoZZL62WWlNrg8Jg6RnnChRUk/E5PLq2bkTxupEtKuNnGAKfEim7bUAjkwJKe13c+vHnLfWUoalgCgogLABVH3KpxjyIFqIBp6jiT/8hMB9yfQTIZzrUnOxEqP7Wu1OT+i2/wTVDoIsuLH2I60FC1kC+tb13/I55EEWWdxzdY2qIgVwEOVkjIA0nJkIkLZp5Sue7d/aA/qC5ObbavhuGKGZYILBArsRzuk6z6hKl0+39H6YcdnnCcm/snPeUNtxStK37gIQH4tKx2kriKAwDgQnwq/IwHwUSc3hQ9dRccN+ilGtoaCY6ohIUykwOEG4XKDD6NzhtWl9i/6pA49Xrq4fC2Udn1ecxrVReq3PM7TK2RYCNDqLWCtUV4vJVCyY8Avf8sRCVKAn3uXdRzKJCZIdIQzBmBGMDdB9wRuaLbhpOCZgxtWqQ8z0mT+DP2B6a9aR+P/PTcDxHEXwlqqmZc6boVWLHTxWvyEomw35IfLnXou/ZdxEyV2Cqr8MEXfbjGTAA4KEeQtciELhprD8oOWYT3iFw+nJHQVNz31kStQvp2WO/gUko5QU+hwGXyRJ/UsYVE+SA1uayZ6QlxWWNXUw1SyWlvenrH2PLChNoHhOkBzX9mbVGUlpbfUS/rjHLpZ5OjD/VdsGMUGzSoitBLLJqpI4/dDQLvYUxMiMxNSSPnXmeP9QMPjv86ASmE0/cRMOSh5KoTFx8IhLZP/7mS56bsQ9F/5uveCjxcMpX+OpdY+MuQifnTXK7I4BryAm4Bjw0Kg2XHh2rghMRPOYsIECVbcj6pXcmwIQSYbF7QTzT3lFyoA2C8Nak/bc1QP1B/oZ+2/Iad/8Exw9B09ay/x0MSI1R4Y7Md9NWP9+MVz9Jkg8FUnTQ2rBKjOZQX70cOzXZ74ggrx+BzHra+9M5+VAWBoE7oDN1/c5cJKaYCfIPaolhyS3xIwuRfjGL6OaZHdLlRvcYBRlI1K/G2E2GpUTYY/wgVoehfCqY8pZ4UDTsFhU1GOC+N+uxiS9JoQI1+FyDMsgb7rJZO/CVMv6o69iKnPaxPaCt5+c2Dad33dQCAopMdsN2cItE2/tRAw1yNg7nVB6jMI/87cW/L6RF7aQdYj3aj0mNmOp11Hpg7uXyg7WogCJuY0CdhHOUZzsuBVZ2SuutvKRagv55Zm6sNWRhIDtOgnZy8XbEu5UtyvyNRc7qTQHBEdYiNwC54IX8Yj3WycAn5oNk1So6Uesfnti9OP/FrqhBLNm/9HVzYc11WhwG89avztTdyeGv5W0BZCYzSrQOHkca3EPdaTF7mnHr5m1KJiRytPACXdpcGrmuiGXIiJQMK7LWbQwkuJ4bVP1KsuoB6N25vHQhRANFTqYmtg7pCHnwx0S5qVVBjzynrSIV/IH33J7+z+VnW0cMnfHmah6chzLSuRk3gJNIyWdVWLHUbDn5ltgKX1eehfNRF8cEhhXOMj6K3lf4zzBEcFxb17JBi2r1Q7nhOPCGytjWedKFth/j3hm4t59ptjIV2A3Jq8VkaBqYGxnr4PTB+drLFYImAk7WbiqY3A0cMiNPAI9UKz+rmLtLea9oelJ0Aw49AlmN++MdC94NBmphrDdQKz4PF+ejnu+HqFqDrETUQiyB/Q4hJmu4BG8CYV1VKP5EXwLZGzQgMRee5PgGOAvnoIzP7dRGjBTkJmfMT/TghPylI7liIUnb3+9ZtOvBJK7Ji/DtCGR4LqIh8p9zE/5J6qDWiq/WZb766xKTtuh+hXjFoHYc4ksC9cNADD98lVrKM3GyrzTgaSRjLSD9MsXNv85LQNGM44eWU2zBh7w4QDOSVCr6vR7SfcyK3sAFZTjmUiBRvngQ7fessaBGmfhOt6X2qOSfHlDCVg/kBokjQoJGbwx8c36TRMd66/QEAze85yotlXIyy7I1PKUIzc69yO2mQ7Ug14zdug5E8sGAcuaNvPiIPBXHpO5MlSs61k3UmKJYxQI5qJb39fT/IBnyzKJTRkS4DnNfj7U95XtI6ePkO6+1TKPozrLNs8exJ44Lmu8buiUJJ6p1W9NqaHB9zmsY2bTUff3K4veCGXQMwMZhKIA9DVUHJq4k2IPjg13iOIlaCcFwAS3Zq/OZTa+wMPQsFiYw6iw+dfsiJXYguKWTzsip+PKfHpBJpJ2kVEW75O4NtARb32IpxRScSxTnfql9aa10F/TBWTmnVtOLvbXVXOnGel6My2Vw/yXv5eUNxxl+63hZY4mfZeqDFFwNn0e6awS3zuapdG3edbPJJD25ieZ2yDswG8aGudMYdt72I4Al1iSlT8LhfzvhERJXyTQA4Cj10U+JAzlw1fKAvOPGta5QBQiU6tBAnfKkFTsP5E3mG0jJ1BzJn1GtrKkwQ2SXn6IGAjKrsNH1DfIxXo8YtlT65gVC7QyeQjpb8uVCU2KUIrmW759BNhQpp/SOFhAzFz7eoL9Ns7URW1Y4ikDOOmniMDaIYptSR8GFmcUsLiaH8dEq0BozKKnD0loFm5YMvH8OkXmeabOvEQ2eN0KrIDBOq6W5xlsKzOVwwk/S3v0sNt/oiHzbGrD40FsDgTECpKuk0p2WPLjCCQvvtg9cMYoi1m9MnoHJdxP7dLmtZ9SFLntPnVeQ0cVvbzQ5h8zvH87rz2H/zkTrZ80zvrXJo+6Apa5cKirsAxzmpW0YSoPjCR7UKC/UtE3inhqr/SiiNqE+a5TpwDApYGMidUXwyMcqOTEvecZWR2J3lvHb4kNpI0qlJYDkraybyf04TP+kX6Vq593KIzJvVx0T6d8P/80p5iBja/1Yeb1Y6HGb2B2CcS3kaWNXEEQuyAa7GaQUhKSGDSIYl/P7T+sco6qOk612CIT/HJsNfB3tAyOdPkXy5ckI4Gr9b+D/DOZbRQKkw2HwVXSMZLi1VFvgmRjakmIvpCJzhWvF04HbI4jICFwRKSH2Yv6rMpQD057o4v5UzWnm8HLaFCN7fvm0m72BBoVbwfn/ZGtUvGg+1ZNkpfmk85nS22+2YkJNYyQFoSIDKpi50/4JyulgFWZ29MaXnzVvAD0eLGuYiM20e6ZQZUEZ95n3aadVoXgyd8dGu/b4zJCYSk0CcSOhJQJZyeOApSmoFeskD0deSqNBOuwiwDYNVr2TvgqqHNWG4FPeOOVpRw+cJCR/EgssP6C1uGu8Y590aPhjGND19aACfbr7dEvoM0bo/ImRTQZy3ayplHLz/sp/c3F3L6MFXg//TqIoQ7/jej+VUpOZgnwG/YoentTvca8xQt5QyRNgme4A7uYVRiEXElSHzFLNxvjxReuGm91HF9nd9P4d1K/dhG8l9Jj79rZJggjKlOaknftb39rCLQvfqWI/+YW7HNPKJ7VrplMmgtEAL5+rpZmnJmYgpBBSb9qJk9CuNvVKte9UVSbLKvtYThC0Vull3Cd9+zj2K0tuvS6YqseMtPRgxZsRKSVpDsxmF9sSuONVP2NXmFHQekNiS5b41Q3RLF+GlPLiDg3t2KD0Cu3u5E3PLypzFit7wnLTvMGcFOtK1LElXcns5lCkoKKRbqQKcDlUhA+FvasdU8mR5SgeVCAAwa8lcnFQU68v8Sblsd00I0j515N9DU5+zT3mTkUQCYtwfxkHeJ38pnlSM3r+kIiU0d9z9VWHWqrAAVyHNhVY5dAYR4qeo6Gdv7ksMyiNHuiHIHRdelqbQWoqsGKc0bzsbHaaQqTIJg1AOaMqtWsEfw2Fs+u6aRIVb6rd/KMhDzWSdfQL9GDfWSw+GYznUS+IycABZzA42uuD5eGAJeuVJaQcZxAj+4eZ7X1zYqvTJhFdFWHYzBfSXXXA2wMXplcUN2UTWgClAt9GupviZAd38LO1oc+NVVClgUY5V+ltvKV2wUVN4tj8gKnR3R1F4YHPVfil7sTzd6bbJlGt42vBZ658cY5sRwcUAJM8uneuFFVT7KSeCA247/Mtmi+O5lckVGJHy+rIM0IdStlGFOX1yk0wJ9zr2lZl3U5Lg17iAPFOkyzde/NWGMyfHcqPE+mJX4ABx/FjvdjtSpZFuIKxGeSU3aUtG2hIOCCvxbzr9s6jBGqaDVTaaobRRCe+p6celXP/Hb3QPlhILnPWtdD4+STJ9Q1ruu39SqFhvAWXBM52TU6bo8eM2cIessvUaOXagb97XV5OK+p6fsHJOOwcTagDhK/rWlYjoqeAUVLI2VHWkarJA9jvt6FYyqOwL9laF0/20YYqQDPn8Q+erYTdGxY6ZcH8QeGOdMhMHucKO53TDxdV5CdHd2rdtUQvczWdVr2/WpDhSWe8Lti93kVsXKtQTpgFwuYXIA+wdSFm3OHkkse7c8FrVp0UZK0CjLj9pEu34Du1+DZ1Wzd/SNWEWAOgSCDNs02k/Ha5mLQKwBWamnSlhBo3rMef2k4xbLUqVdoG/9Xi6i/D9NeCSOcWA9mn68HfH5N0Unwp1RdD61iP4HUD+6RSFM1HiDbmwlfwUN9nM16M7HgrcZN8vUIoLqI2o04mrvdu9nRsFIxadOBeJwb5VKjVgQiwDUBdkiTP+2nYKEcoE7bJwh8c5ILVJMTFgrzTepoyh69fwlHDE7IK9Qu16naeM1AIK0hmsfoPdJ3klfC3WQeYYhmxdNKmgjtOVCsAUA5GBk2F8cLxIW8xPFFqMh9FRJbqvpaH1l/2ek+gl+HV3gRhjYPfaFuUb6B3S9Y8rPpZzoOYmuID2NpOA+t99W46K+3BzExnnlnWar81WprpVvR3UY13Sft2CIsLblkxOtksn7ZsFO7NuJqdgqYCscsdtBCYRkqbHHDtWu1h7VUih1RS7uRpTkYndhU6EgonpsSlE20OBLMRhkdJbwsqd2xpb81/wxRx56UfkaDbGJbNgOQFm/pmLub0r/m0SA2R9nTET5GiBqvkbpj9D//ftiGiWHMfYtac6gTHIgJIY3GCIF+KTH+cdV1YRUoWz90Ifp1VTO/IdBFRV4vWZqvQQ1UfhREwvy+wL7wgRi+TvTFapG2OHngUqZrgJPQKurOzb2R7cdVOlGCtbROTA23lY5uAE7dW9xcm5tAj1lAXaJ8vxvVjlHK9+LmBBpZa4EJ9kn/WKp/SHfDzSAIBAy0n+Pu8BxERGbRT4EmAAhavxk+EprlAGTQQwg7uEw1icep/fO9pzmZfNIDHsUXZF3vgdnOdKmwuxM2gjSKYcODpzDIWzUbR43ltkNaYONjmvpnSd0oM9bOTHt5j1G5Z9ZV1cqDmOW0ShDlQLbxP6P45G+JbcH4GplYKvz4iowtwo2i8E0oAWKKJRdm3M0Yu2WAPSJq1mf6JrRv0cZpNimG2YBSFJFcRdxOhAAdvWuAG+C3ITuW3bd+toYBQXSqjhjpQYcXHJyqmKw869WBX4EbEji2utQaH0Vm9tWsuMS272HCIEkkMS4bXQYE7AKk39x35gz4snIWQNgWRfJDrx8hewYzvfm4Uq5zD4AorUZYqyfHphbxrWPGUvSwP+4BNe3ulXLi2r0DfioZkbhFV282cyHgJSR+6FbOdeQ4S4c19h+PKByq1uXDRSXC7FGpLj5eQFJg7/0hRJXAhxXZ9+CHnQjp7jqGbwDJm0P/BcF0U67e0DJrFxFciREgoPhbfWitArVGC7xf/P0nNHxnMQrn5ZtmVO/5wH79t6ZCTaiTvLdMMyHML8ymubVWkG9ncX+1ywARre/Tfo+5IUvA9xb6lwG3F3kKHv/BkBBQjhH9sgNLxNck/k8PiXy5CJ/66AMskUEaMRJMAFfz+qdwlaBeuutGRjBuXpdR4pFPrKHmmYfQhaOLpiqVw/zhAEMIyhlXKPj1vPqI46Vwipou8MBnb8gzVxSwc9YSHMPBj21VlMLZkwSbkAuwdIIkB+eNfvTsL6Kow3DRrl3VEdamoTFBD3CZigeaXlrYtCazdjXSQ+UxBECLqE85dUz3Qh7uhC0sbWhLk96sE4pnrFn3DPoYhC/2aqX90sFZH21drBs75VrZGrGRw96FimVnkw8O06hYfqOInQPbbKQdBXD/i0cF1SxXtjMzUJWtE1VBoAUiTtX8wCzEMzzoTf4vODBgWNX1bVrcoXi0d4zE3mTlO+4gRm9Bea1ACC/cyGIyKRivrTd/pZFET47iGVWMHgJnENDxCzoKuWFbXFCsrDFKKjr3PS4S3UgJ/3tO68mF51vnkeSxf1uABwwD+D2Nh5pf0YscnFkUklE7SpbyJzRSj6NOqHwb4vJkHsFtXjDBUukvpv43zwB9LLwBR1mnvikG3a+r5/lzMDOtJBI3eeD8OoSJw/QpfDVJdk3efVQpwmD6HHI2GUtkPj6Ib4unb88jnB9wZ+lN1YZjvcOPZWUehjSvyjoq/+nZTodlPnkwLpm7Rgl/08w56RcMdn7ch047DhpLx1QIVaVCMClz9k/mqfDibmhkfz9laaWCNbxApnRgKFtxI7Vp1XzyYnIXXDCdfidsWJRqQLw2hjcB566RHVpr8vx8AdlWCBTwdjzRKqTwC5RKJJLyEf+AHhLP0uyCPTwLrpqFsCZUyN16QF3Ue3UuRUcAlEBIWaBpDPlkHNOQyPh8LGedzA5XewYFiMy7FF7MBHlqk0Y7WW2jTzRh2OuASh3Jh4rrxgyYFIEkVnQJxZud11qjaN07+EjX2uMh1L6f/bPOSBvbuatkeWluk6N4JFytj9z2PCkU/OO8A4keCwssMj4Io5XaAJxgdWJoZbC7Tj/bziKp/blAjuS4vDndzW1PDdGZ2H4gQvhXChQAFnOctiQGCO5U7W1mlP1t+aP+LXHvykvETATDoOL0hnj4IWTBDJm7/XNX/KGxPmuf0pVnXZ08CoklGMSjaxk9elKRloLmjebt6NT7flbmMprU9kpzJIFofT2I8Jp61bEtXx8gSY7XRMkr0JCKraWGhE62bztRbcTXUk73UHEiOFuDEZe3NvA0KIeAe3mKsWfJOzdlfAkyH1w+btnHw/U8fRmyHJR5KcLFSxq0vSK8/dCj6+7YEU0GB8SW+afmXmS3AlT260CzxMlc1yxgCxqvDdUdk/zEoHSLhNxW0oqVULK93rRXzJHafBtRfKs2cB1dKkvrinHB+qH3m1182f6QX0KPanpQdPXBLBeLlrHwWuHuoja4zWvpPYrTy7s4r9FV9zZuyHKdqb0Wp3S26oqOXb3IlZoZG1DfLEXmOah6M6hAa/bWt6lF7kd2xMHwH+4qn17QB2YHHiDX4O1PGJU0bAl+DVyXr2+C2hp15lhsWSrQ+GSB2gyNSLqPie37lwbRpfFYZSvBFAkdtXolaeptvAiLM7/LuzKF8mA/KGP+GzlqZ1iDN28lNSmYYFHv/iQWItHwRzfBGJXtaS1im9E0y3n+SiW6OYg80xcs4h0Q8iGr4CbaBABNZly/ig8NrBC49tXFoWZVaEnP3MEu6zZ6QrmSZkBCDGb5fZDpBQlUI2ecBoPxoI4lIak3y0EjnEVACsjnfP1XU8BSpobOqZRZi/LEbIKNGnL2XL9uf7cP2U25oq3qne9ud6MCcqC7SHbsYYBq9CH+jvKmFkbwlEz0Pqbd0gKKiCuibvJnxoD0irPL1Myg8KnqexD+pfucUchtH9jzj/xzXvERbsCMq9yMw8ipKB3cfRxfa5HTmUNapyXuzIJekjOrK856oU/jEgD9Sy/P8SZ8X5Gy/bp/Wl6uI1LslePH3ziYYu4HkOeWPoG/5QsfvVn6xpxCn6A2TycL2owell/EUskdLlgAsNUsRwaqtj6C2x5mptow8hwWUadoK9wB6eykE1vYRd2aCt0hSIuhWdNAVRZwp8aucK7fLwZ+N1j2fucrfQ/6ilFfgckOKRX4vcyBWqsqceWCach4pfPk4GHY6Iav1zvaX5RVxKGfokc7a2tjqNdpQit4GtzgnNx+SOD80Hy+tDdv4kQHw8rlNI/8CooD4Nm+wiuntHg+CydNXDtbViCuAZl1Yc2SveZKTyTf4uSf6qRnDnEN7cjk6hUx2HdvdyMF7UMb+N34CiFiRbEsQJoeeqUDRWc1Hrrd4ktOEWEH6uuqgtXBg/NPldXarew72JMjS/LZX8EdhUECQZDko7hpOe0vtnNyyefV2R7QtfgJOn/5GlxGBMIWgII+JBxcNpkjngy++p7e4BUDMbKqjKg4vpzu2I4rl66vZFqsrkvyhlEC3iICBYoBcVJnM3EqEsglKIU5nTQVvEuUbITEsr34ALWaQG9rmVr7kDsxArFSOu4ZR8ml5HnhtV8SEZD8SCxwrmqGcvmK7DYZZG5+vVLuluRjommJQVaFAZrSFV22+xXconnJuPfPw6Tef8eXdjFlB4Gsm6iAT2fhHiWgh8I34FWs4d/ATeM5s5rlCKqTYwYNA8LWwgqQbrYMSkQrKQ5Sn47Z3/0WhrF3EQ9kN75x2ldQ787wIvokSg7gFPd/Le1lGqPwBWBxlfIf0Ijs9PqdCSnh6vS5G/vP1LSgq51HX3GW4e+GIQdkvHp1WZ6kxGGeqXQFbZE35vQrUVss7TGml/pMc3tcg5wGiOz0ujIGCfoUAmQ9fk+0hvRs/EO7xd3KVcmQa7VNaYFlaQBcBHXyruCyosp5pT8pg1pIhFuey7pS2nA5cR07iW6e3/bd7N8l2BnpMQ0Z7y5z/62LWI+MgQxVhYSGgquvD7yiso2YTy0K2Me5gy/4pIY/fOdI76eOf1fPWtKJGk93y0UDb9fYW1QVpx+CdtdaUQuI1h/EoDjQ3KOBOFaqG1ZLEmQZStMY40f+GCW5eU/PCLo7DFT60GrUiz2UklAYvAekyJ6RaaJC0q5KAXcq8G3UJnDLfCzdX8qpf+rh4rjWqaesmZ0pEskSrkz+t3/4C7+pLGyiaXSMRzfpTamKmlJ4rYvuU9aAIHzwODMZnd7BRMa0q9IVaa5w55twqqkgi6ZEp3HK0CEwgQpUK5ELDuwahzqaPIVw48Iq28fiIkUHjOfSjTu6NnbkJj2jd35O6nLFMAmM86lfjdDQuBqKVLvzoZ1vD5e45ZSfwAwStzKZyIIkmVPsH2hUAq638X9ceLEHSQBwjX8pW9H5k2NEWzZpC2xpqy4L0PmzY2DzacooJwa6nvUWCF7mMud4h668xPwjWoILL/hhoHZ7EPJyVKcN1VmNSp569ZRVuYlwfYDkRnimOgD/d41ewQb3ul8nGWcyiSvdXQPFl+elva4W/7Z3CRAhVGJtuXUr8xRbQOVf5h5R3KWyIbdQiJ0+7G78ciuAZbKzixA9fXIYLnhlweA1b2rTy43CXpnKINYl+PfRVd9zqJPdXNB58RJxJ7cBD5Z0upLkJJ0tQBp4ES4vcAiS0Ea6AwUqAxGnxV97VsFU3cZigs8dmTO6+j+fbLo0MF3tYyiAkk8D4wkkPyQ0vSYGgS2w8gpkCeOLTCSbbSiAI8FCL7SR6J7ZPqKRSoWIzzdk5zAJtw2VRydWHZ9gxpf1DQAQqBegLLTXA0JN62UpIlCF1LUZIvIsCwFDJYs+dYoTBskjnoB9JAPwJ8gecwXfWUUmxl3vodScQ96pT1OPXBLOyGzy+D93FlWHOSudxmLDO7qXmfep1YfsENVlxeVoUEOfYCCq6yYZ8zdTnBBEkk5jqC5wMb0LMM/JPPJZIoLF1Pzl0hy1Z3F57M98p/9F7q2ZGe8Fp9Hr3gmyIDCmUZswdOxqNV8Jsic5BV2Kx4fbFOg4Ajcx9UkFneCBNBrowCXSoBDeM7HK4vj1CicMQG6o/A/AmSJmAeJkDU9Sg5YeRaauplS2cG400N+ut2dLZIOqap6+9iuN9xTCMzeDjN+4QXqMplup6JPYuHP424RIbCNiTl3oyA4SYzC2MQdN2KuhzDjZS6h9R1wKTVIDOtgifAtyvj3iajFrNBWwi4bGZ2j0adndmTtLYEAyjKHit95+l+fmhHs4e9bzh79pJztLIvWAfZHmqHZ8e7TsNHcxgPPe8eeK4XSkg6XD7NBjfdz/+acz8OnGDgzQW+3SOXCVABOWzLEOW2oYDTZTkoh35X9lp0LUPOOnZu/FUIPPEpSnmIBiADjcCHS58v0I/vzir7hBjfi0fxLnhz69xBSo9C/1NQB89XNJCut0IGTnH5lJuloYkYsl8wqKU0iGtei7gkmAJonHOcrrNmfkMizLCmjYeclOF3WS/55vQBWf41yUt9Q0m7gYVRPfD5/zxdzO1/xQybMBFGvtWKeq8v3sAq0rhtomQWdhsBrPWdKQbVTytCskc+jpaIVrQHO0w2EfyICIgV67CpXLMM3zgJuU38/m8O5zj1tpAIUuE7Me9vBAC/KSZb34MdOtc6A9aJJbuD5NjNaT3apXla2bXs8baRznPfSsZ+aPw2aU9A9K6p8izvT8/gbdlnBGdedAR/T/FkJNI5wwF2xTIhr/u4V720NtYBqG/ruBjy3MgvXhgmtREB/Psx+GWzWI/ikPEAmquXUigKi63/lv5YRWr/upTkcsZ/mughZvQ0uY5FgEB5w0j1CUsv3f9pgBUrmMUOTSwAMV0scgBfYZ0i2XVK3cPe2WU+VaIRkG+zssadOp4u1/Kg3OBMPmKvLJFoLHWVqwWY+hdv8UIVJTkYuq6s/YFDgUW6zjiKmFryyw1YN1jp1iLrg61QgpKIIGln3MquiY9C5+/5cU+KCD5v9RgNw7xl46GKfZcsnfl60NM7jsZssgkik/9UxqyPxzRNBfnlYJWU4oZSusWPtUAjKi8N6LsgsNZ6SNowwaqh7ZWS2VlID9Q+Jfmk/0x8KX09JhTTh8EfW8A+uM8wI89YLSWlx4EfUzMP6XCVTUTQ000WOjBKUjN3zBXP28GjMSI1SYfXhSnFcvATQ7fjOoqnXVdAS9hwjU6kb2unLqJdafmSZXMDAdqCROEaONT2DinWA3v0jP6mXBHKMDQrU5wuw5GSlmwUfCIy3TzjKyiRoIASa8mjTewJ63pltDsQlY7uYkBzCJQZN9UqfYIl9pMDw25ySYvKQ53+Bu1PomAnF63VW6w68z3JDhvtWv6MLDj4SbQ1tmEPyqExT1HpF29egNKlsSu2A8d6B0eBbenB6REkbZ0ueYaUGLLCol4vfctWaAXwuKQr2GzuAr92c2PGyLZgy4RwW8rPCzQ7DVy+r4CKuKKUK/+ssRGhmJySylk1eFA5XWLD2zT/rZrS0I1KUe5g5pNIQTHLpk89bPvwoIC8/oeL1Lw+R2AMomZcQ9WiVqsAvm/9pNln7gzl+0h6x1vvoVJSe/7jrZRK7CB+qSAcqb55d6VIp+fLvO3zDzxuZAU8l6DiPCMj71PKVazilPCkcUagBC1JLoRpTO08WgocJQCdLvN+GJ1zWcx00dUzuUpTjrmxCipRLQHEGLZsOL9ZOKL0N488GX4BxrG4lbCMSSiwvtoQvrgBtSdQ0aRCux1y9KKvJXDHxsmJLJJP0KLsc45M/CMGCSlL3Y2wqvNYklIxuQNb5IqLEpifLAB4aimsNmVEnnLT0lVzME8MieB6WUAgzdjLZWZfTdOqyCxA/0Kvg4S1gM9X6wKHO0lQ9odXwcQRFH6K/u5gkifkCEl5FWRGmYMUMRH+FggqdLrFqof221dchOWGoHxQcaFkB9RF0wpRFYhBWujNuI5n8vSvZy/gqGmlwNFjibU1/3cJQRF8XSWIvuDJwnr3zv+zQOAD7PIm51N7P+7AOI4lqp0OsqcSaCw8Y90hi3H32DAXpqnPE87vg9VrtzK0o2IDBjYa4Ow+P4FtFvJxaSn8zq5U5Dd9VXSisZSByW4G03WNKGi0v2dZJSVnQuW/M06pbtVgjJsIPAm1p5REoqwVtZy4Ze6BPMQ3oON2qyyeXeTmJZiK3+8di7IemLmpxtesGAXBI4NUSt5k0/DdyCntZJ7CyKkgpXhtbJ4B9xNte8up+2VL4d9dLqJ7lVHntgpj/Xk6C3aAg543UvykV0oLH0SkAEzwQ9e4OGn4neZDuWy9q+PreaH7dTmo4Mlt+p7WtUXbvrrz6263ZfObCjj74q2hizx/fzlCDSlxVwdFRBuxNHm0rSVC2ycSjfpU5JnluTk/WMbXJbhyWHgxm/wz/BIQ08uyYuKAd+BSMj+G/JZZj8zGC8t4WoIywA3c4HfNemkUcGAwwcrkFY2R/AThH2zu9fphuNYadINnMWfTFKbHTkwJvGuQhbWlaxvRW6+4xtb2H8mQlpicMWTpW5oBVLlAlgTV/RmUYqIfxDICT7GEbERkM3yPTVQLyUI+Zyg5Xg5svUlygT8QzWArv/+s3q00GNUKNn7S15RrFfTj2doXrcJw3VOFGqLl3s9hiDZ0aSr1FBeOtVOi5qM/u91KP81BsaXgTsJJSCeLghqTn6ONYSou17pPMYG9kGlzoVygKsuOlaUGFdov9IJ/4wSljHVfkW5v6N1hhHigOInc75NqO67uPedNXjlXHNpP10wuoO3uAvyYWEp9pN4fUR54OG2oXQhoVnxf4etNtJNZMQPMAo8I/YLz+NOiELiKD9YUZosKY1Iw8AxtFCXU4OdjvZ8K0RtDLFAwCZeKh4R5vAX5IkL6i1L2nCMymOXbmZWLWmeZaZUfwUvh0eQl26cvjU0JwT3I8SCb3U6u009OBFIj5e+XEfRLP0nLLlQZIEHfSSlJPPalH/aV7nALDzd/BBRjBNGU9nmFTCdazljo7I1fL3to96dQNwPNfmNdbYZu0zr+RlgiZ7ldkfpWApt6uNRyMtqSvR08YwlGXtJnPF/VYZXzvu8nR+9D32a33Ef0FbQQg/ulgRv1OgP131CrrGyzyIaupz7DWNfnVZJAJlmI37BULHcIhsKMEhwhnvxKmN1PO9XVQaKR8MQ7yW5hefgi69g4pxgOHzEpt0NKgRIlsWsu5wMMkaUAzac9I6Viyk9KnUNe4FoDj4sRVcd+5P9WYFbmSmlgsq0gYTYxDPCxqfSKlwELOSmGzOg4jdji1CUM7JAfr6vD6nJZ0Vw6PXwUh0hkzl/C9gCI5bF5wP1Db3fUfk1oUafi+Jhl09g9jLaSkY1skJrVxBQ3D5DAZcIZAT88My8VK0EeYAEnKlmtUyl7J//WBRTE4kRw/Yuczm1EftJqm7Rt49TaIdGqAW0rPIv2/NR6KpYvqGlhDOaqHSyn22FVvOnzSj0seaFGUWkHAR1mgxZ0+X2icyYM6GbkpvhbxPLWR1xwfo1KO1cesL3v56Xph6u1/jCC5+XnnwjWPf8r59zeemR4LVTebjawlGyD/b4ju225jDN5oTBUW7B/SGY5UtJ4hALLti7Het0AaulScC/zxYJEcRL9Yp49EvlGAHm4Y/qFN9OUBvKOHYLg30ue3yJ3zmqz32720mayhudBTP6SKsakWOoK3iwtL5GbyFe64KHFftjlC3h2Q3WboQh9828asuyGJ5zdlSZmLQLq5ZpdHqMv/X581REFPA4V99q89ssZu/x+xxnW+CjNxm4RD5sDI/TdBqOQ4bI/xQEv8DG9wPVJW1048+ARYqn/13CpJ4joeoeHg88eqwwvZwOoylXZ/fKNb/OP6CRv6/ABBj/iA+sosFEcB4SKKHSrpjMkf428Uw4e416ZWA801ELIU7wbHSVXjS0iRj/BOnXE5iFmE3okr7pDA61oz/WmiqK5H6jifYHnicVGb9kD/fbPN5F76m8n7XDYiajXe3/6TzJYlWFOeWPkRauMb8XsEXB2URjGDLF+Qcj0oF1HjHJLb40Yk8pj+yNn4gyM+6yKr/m299lePdYh9wIu18cv4P3k55V1UzuPR4PuHUEUQgv+8+rseRwlxK68apqDKUYlYXvxlNdrfRRWGgyetWCYTAoxB06pEIhvmQ8C7nsIW/9OFS393m542slEK3WP4GS0NEUAb6PY8ws3aZGvthBx+nvKgKG2eL2D49pLB4DIkcO0nm8hMQ6gf2CWUmjBKWTbcsE9g15dkiY2aqdlnXJqBS8ANuX+g2PmF6ryCuBB/2auBZ4kJoR3C8HJ5D7/NpiRjBvdk7p48qvk3oDQfxVN2W5Iktad4zCylmURRDJ0M57HsYsqMpXCCXttPnUfOsJvb0Y1iXkDd2guWjZq5sdBxzixW0+UFwSKoLMqwKQagf/YGFNZKWaG8yCOF4Jk4htMyrvosLadZdmSUdXLLdM1ElKUCWBihPg8ccvuLMrJKqlusFkGPLLr6nUgn8tEvWaQKX8aRaoI35vNQW7mlcmWS6vmcCqg4eAQGplArE1Kr5D8kyH/ViuraonUf4gu1VjzekOCW4UkqKceuRZ8UrBMAlxwdaCu3gGjH/3F25aKqeA/1GzbOy5xPmLSv+rwsDYJY9YjTXEcwxmAWqXAOiY/XQNDNjX1zfC5JJLzVWMJUBu1nMAA6WjrIJk9jKaXX6KtRcVu0+KMJ4Pj9LVNBUrZM5Q9O03scruAJBuO/7xtd0EiUt2ngPzXO025bb13HZktWMtJt6mauNpZ/3ZnL+bLDk60vwqiGAuah3bL8PdFNrtsf4yH0r1ghfpdlvanp92+8b6o68THLnuIo54UvHuWYyn5oiYLCk7NmBnPVgEnEdftUmkkH1Ypn5g02mbC9+O15n+/taCqEkymxF2Jc1Iygm6rocckhv8F1OGlPoE3L+YTPx1YXZ73cyDotyFxBKVS4Uhf7b++9PhaDqr35qk8Y3/ScqAUfFpmylWDbFEXFRNRy6oeKDFMU+R4tt2Vi+jqnqMcHwTBpOupoFmXHV2PEodSXjSuagDkkiY4vRJ+KIYlwoDixE7CpLqA/QwwLP/JECFM99QJrSdTfn/7wBYdUKhq7k9AxkPiqnQw4UBbKFTFvPRfSz1zVtg9hCnknGJJpyz86voRZs7Z5Ncl2zH4GhTX3uxssnfGEuKycpUUm7+eWHVeFB6c+icJc73HiyocZVzHgXPg97iU3TbC9v3EwoQNwGUq4ZiwDQyCcZdqT9g+3oWliemF2HOcKNlXJjQ155fsg2Mm/UyqFuQTbNYM4KxyMosRPsSc5suwQpyaI6G59fruuds2mG7bJPOH8m5ClFXhdu/hiDL6mYEnY6583tqaq6dXzhp8XeP7v9d2oGgUb/obQHWEblqnZNu1/+5XtFKH5gg04h8YOSZUZ/YdontNVAyTzguQifAsQKhodvWwlgzAqlxJBGYT56c+k7UthMJE5uoV+T10H4Ke5vzUQX+CjtEMKH/M5RRIok0hf6/N89GOJ4FkiaUnXHJnMA68j+8XUvQpOa5o13pkHwQuufbQtsCzelamHG+krFbJ4D5Z5x2ME59dZQ4wR10ZfegmHtGLvuWigQlJ4zRsuOcyhlCpJv9tyB7dU/j1mtavgP2MR/5KVMjoQSatXWHe6r0WoSJ25wRtI2k8H3JZqIHTbO2Z8OTtmBTAEoGABPjhlWwuY6QTvr9bmlSQkFV16+kNrXpFj4a0FTumDrdrJ/3r0nFGwTHiYGKKzY/cNTFt+Gz95C/uXWrd9O1DNm6lvx8v76YDKWF7qrmOXRAJRp+EozIxBDdnCFKlssk0lipcNK0Xf9gvvnlAHqxDACxpvxsjq16fitLK7v5rxQRa5GZ1i+G0UXq+ATKazL/itnKMdpOHSHud5/HhmVnPiULEQxHGBEKEKHZLBHEO1+qvgBvTsf8OnMndZ+HrxNoMEPP1qRQbOOM2rx96VUt4hACR+llkE8ewXwWKPROru+EWhJTWpLEMdhhWU6h3mkzv4nMK5xBqt4C118MhjZpESiXsTjqqdsT5D6POuu43cfYdboNdCviP+scm3b1O4RDwrT0i6i4/yL13aUpDb/xjtFF5XIJ9puGQ5dalVXtN8vBGpRQ0uuvhVNfqKmJV1tzYiboC2gVz/X7Zy0mvLUlzaAkpnnAbbEscf6QHS4j5P5NwxwC3UVaNsNfekcrkbyVDPiB1oKtyG79zlx+02xNNVwZlSF8heQAuqESdTcqFVdydLtr4PJurfu1CfpK56+WBnAoRplmRoWhZ7w+Kua+V4wLqVoe7YFH6IUNt8lpJlHSjLG8S5tzOMejv5QwMWyZCfpsQM5+Lq8sLLCdh9DBfdmmvNMj0/2VEYrdtuGtkSCVcuVT7u4mbmKJ/a+eKdPy+z9OoqGFXpWwEUxkBPu437dHmiiYR+FNEdcxPuUY2our0VESoJwSGbiKNm5HAeWWOC3XTlEyoJlJtX8+2PO47v22KEzX+RPuwqALE/XJMxhERTAOIfMmsArKTHaDWFAPoJVD5kvGMNW0aOZ4nxaLSX+zgItvHT8nBSB0vbOPN78ZZob+zAAz5bOrch4B1tA25GgukSFNymHWhVNziOgBKptwHl0VK965LS83R4h8WYnTOlpF+sB34/D29nse3B6epj5W8VRf4KpiOmf3GQXEf6zwNkhO3WIFpemCk0lejNduC5HcBtREfaAjoDzNFl4sAJNyhzlbF9qmaS7kSSFfJFTgMX73UKzust+KYNuGAsNdlRk3DcFZoDR3WZTM5tA6xQ4t2tdaQ5dbxxxMn1LXcNsnVUh6sBKH98ej2IxIt3HU8rqTF8Bs11rkC+JSZJVdiolB7otD9NzkxcRy5BH5r+c/+DJzccYcZIQ/fql3zeNuECtCXX6zfg06cfuD00/CutzHpZEjUvf9SVEbUgJCUsSnDyotA9T5MIwtxXBAzP0XT/jtuqn78o/tlVfOh60HqEuf85udtbF5cz/Yyl2zErYUReFmkIR3zjhn4grec/ImoaW6xY54GcsQKWD5R4Ynj2rlWvwjq2e5hjYaQB1Zd7Hg5b2LE/pwYhAEl3jQMmg+XHBwUaLLI4GLBIKDzxUXTNTL8zySpv5BrdbF0HllohnvjCTRftsPuwI4EPy/dG8WUByACqf+MCyCme/qLu4WRhWKI52hcgUsxw3+WrSGVOU6SzC6ttmEgzxZNOBBR+ovIF80tIIxS1sM6qxYz55QsDEHM/pHC5Ts0Y9ne9g4sdYufiaShOI0OM1zsQCxrwIXoXCdvn8j2nlPt4SqR3sIzlDs8hIPY0dD2GimqXmULJXhwN8/KPeyOdXA8LKLMpNZhouO6DjO2tJWh+ygiNoIPRGSoK+w09iSYHywZyx8A9HeNI+2Xa8mJpSTvXonRFgtWmMJTZeKYaQZMqCdO05WvzUzEAHTnzMzerVNuoUsvW/pSdkNcEa8txGmp+hZwFNHbqoLxmeldAmNiNTWIHEiqgWRvrFhXQnk1139clEAZ1SMaoXFWavNlb9qNvx/57mBmiIstUlK5KQ8ArpNOZ4Jt2n0FF5xytCzI3JybRA/25SSTG2MHQx1qmZAa71G/A+NwstXAgYC2z6CzDinb/89i6gf9ywC8VxIT24x/l2i27X76Tzr8kyIh8BSilOJgY0tjaT1vAj9KJ9YKliQ9XTVnDyQXwctMjpvklmcPbSpFh3OjIqiZg3mRQhVzP+sjPJY1G6p4MyMsq/Wo83n27or9zQcqcDSzjjqIL0uwX3+v0xoCJakZgEObB/3iw+zUJ+YHr64/W/H5d5VJvAyYRD61D2yYqVptzu+w/KwrM5XZfjbXzbl/VpCPuxMnzP3F23vCpG3hj9RsIfMEfeAAFZRoUmFbEaKQPMpKK0bKaJLnRhJxV/qtTfZSGTTG3AnSAmIs0asPTGnLxCJqGDBYuWoT5FSt74DWgTWXKBfReyVWOF+L9lb6b8fXsoXZ/fLWZNF+jr8frIgwMLqQoJm2vfJ9CPF2cONTXin2xWIIy4aONwWNgqeX6K9QYx6KzoFG832H/USKTPtcuvKY8d9vFNcWiuAwXhgX9eL0KsB/le+fAJsqCcssGyqsX6O8w6m15aksgaEmc9mI7uI3rmxHmLbdhccrp7g78yk+eXD6zj2wOQecTxLP5oSe3S8k3AeSsuVhZu3jmgti+GW3YTyYNxFixmGLmChrT7nOfSxVCHJVudWlP2rJohf0fr99rUFQLksyqGtjcK8RuoP7AFYswP3gaWRyqSA/bXAuZNZD9GKrbQSl/+AfcGAopd5aYtmbzvloxoHB8IztC1e9eb0n4tokedub6sdsY+mJkRPOQh32rftToBw2SfHUL4gX26bnkd/Wx8DSGGDFyKgOVAtwT6OPxtMfYTxQq/sFlGREXrBppLOpvA6mGat1f3sBODcvBL9gXxSLT5vVTLdlPxfZPem+vutVdSfvsterFMUa6kapnqgbEBjF6MZzyhv9Ju2WVCGkFzWVgXiaU2unfIC/oiCnbGZ/b6KGLVMBCyFTdkNaxmGs9vUS8JqTtexjVGSPrd8pglGXiwNXccHBrUIgPzLZoam5tcsAC1KqJ08rsXbRGQ87uULaRT0hUVD5e+QQUm4gKqWHu9yK6A6Pf4D9sIIMDAXQm3VD6RT6cnmz0QiBBJezc67ccIcL8bW/tAHHxzD/c4Uohtb2c2od0hGyVGHP2zLvT7JrzMy5tD6jaUr8P2V1vIpGKcyhOhCrNqt9CuWYGttIJOphrqrruz1wunYL1vKV9LncxJ/fMTw8df4HBJWqQq0dgfPGoDJ82KEcuZgsyR4SmwoadBH1braitFg+fihUdoLnNLx83uQ/eszoMhU3q/85QyZpoKoaU8j7rORb54w0cVRh6syVLZLNriwzXtpBN4MCmnixRhAUQxV1iqoMJ83mi/OwMH+yMWaobjDFBQQo+v6bd6R8TEOhw8KA4yNyOuN0gxdIr+jKF6nDBrJszB9UK1iUcjY6LbXgNyvDXrZnb0g30vt2bXnRzTWNjBzqesRvt9ZYlM/MLEq6ncgXLVf5/jXD9KQDa+ahrSpOWQWSGATGyfusN+0t25D65pUj1/U+Q+P8Y3KRLKL9TW39t9mX+cKZVxjkzQOxJckZw+/BlL/SBrh6h0dz8wVzuFJIqwpkjaSpxvnIA6yKFoAthQFjs98wSXpTwFQP/ZtU3cmDOGHIEa9PhiHHl6euG7I3iZLBV4jiwiGTgYL4y0f0cpVcEXIGWf7BZLu+IK0m/aJ1HaNt2iRXcrYi9vwL9WwUc6p7zTpW9G9DlVQhkKqM0HC96Pw0thNOXZ/1/e60tu/9VwVY/6SlQpnB5gl1nHfB0eTkEbq6LRTRQbPx0rJA28GzxJJAzbfu81awtmqjQ3xxC/fv1UmgM/wu8+1avBMHpYuLWNECg/M8VitMf3o8ML7I4R+vS6GzXRkSEztfDUtJnvQs3AzxdUoQy0oiUDJTB5z4Y89GpXGoamuJo5T2+beREWjHCVvpmzTAd0JW9AlHIXSpopl+Qvgs8usu+OeCOA0jN8u6mvCG5c1NDB48JIzhhKbMpjCELhDaBbkmqSkzk1wRotmGyxunxI2EXKnFkcTWRPn7KsiYJo2bkTNvYMkP93hh42099VmSV+0I06UVH4pz8V5VgDr1bV96dFKBrk6uv7ImXoZGx9Ip6FLW2k45PYCYEGr7nltYVZeQY4xwWHIyup+y+uZQaFXj5DOVEB/xUG0+blDpuht0wkfsQJmp62tilI1DXjWv5kBBfNizCnWzekwrAYBS1uWxMTdhCXKlyK9NSNDUjvIONmTTZ1GIVWTz1EpFmFDurlYCQaBpKJ1Thx4irfFWl9zjmvag58mnvffDA0SDZTFEzQ0WF9YW9zfCqAAlTotiagCmnsqWwn5+mMT5osecrl4KnYZEX+bTzapwVYwJdYcp3JmysQzCOcHDAejb5ICLEOTP8xF5j2cDegC/SDXcwmCy/ZoAIF73U47/M3fG8x3iWyckyv6h2JYZbU1gkvHzvSZvIJeIfWusuM04ihzPwgyZ9i7JDeSrY8ivwo9Dl1+w283xaUZJU4RzGgbm7DDfLa5OhVPxp3G0NVk1uzFlDPOyibMawpIFgUCN085jDHuT79Ir1EcD2Ll3mgiQK4JML737kvr4FBFfMMtJyN+eWE56I4Y9m641Vqe2axt7rUXUukxQv5LTLf/bvmJq/U/68hLCSAbQw1+jgcdoteeFnkSfEFGC+d/1g8B+PYLPLYSDZsW9/PxWxsTiyZ4JrT5+oEsa0Sq423CT+HIFgKLh9MROIPAKS4zNC4mbmDhQbcE0xhw71vob2XXbgzDO1ybmIo0m/IOpb8rxZG8yamcDvFH4cR3RsbJSbs6vGf2+2ZnrqPjCj37ikj5y4PWZ3CPL8/Kf4Mdf5aA+EizxZM5pG+PNekATrPZW87tMYq1k/rIR2Tc/CbIcTiI4b1/Xnyk+0gptmgbxrvOjcRibps3jOmNvyl6FCmFfyHMeeHDaBYS4N3wa6bNnMxuoMnTz+Bzc5wo3341VIAMtGh1uTD7SvN7ZAqLa+CPB/utaUGeMscGqjfLsghi1TmMsi+qG2KEQPAHx8i89ZvsUHeKgWLgjq05dPwtgkF5hfd2sapGzuF7ZvpKvCiuq0k4vZSjOKVeL9AIP66SiEDHzYl153Vg/suveLGbS8XkeT+BYM8nM+4Kj9yqoWCbjGGAJbBxCCP40WVVzNyUyvtObF18GcKVcuRXxocLI5T/vfB9WI44BC3iFKptvt3BXJlOQYZidIyOT5KB3BmhY/tW24LEN+JkqVaDwtghql3HgnOEWD3yNX6U1ATYqWIEIbmMNH1xDKcRa15qMqyvRI04fWuLqIyFl30Yaqfp+hmng90baAJp8RvhE5H1mU3Sj7An2kl9/+Mb5fZzjEO3PDpSl4GsV5Rm9iZQe8gAvpdD+ko9TwOjjolpuolrjKU86qULZsmSq937NHrRxcM15A7ueq21bKPJtwMik1f6C6zxOBRcuHmE2J5MnnVDxi5RdXFRk2RLIxRO3/lP1nJsaAqzSNFVi2e9gh3MvgbOFUqWYNwQyqhseUr3sOpff5LiIKivP43KmmkVQxY1KtxBJa+12woB1dTzVT3zhcnRM+mm/Brre3a3lfxwWRso0A5purjPppX9MRYGe5OQgul/1EPkr7ma1cT+myPiWWfm9bkQspXZHjlmfh6f83vIRGavZda8CqW7PYK7o9+huWORmUEQTv3YbXdqAbUzpa5qGNqyXsSfoRN3xqBPvqClXxIamN1X8L4C/TXtOmB+k4UaHyyOmJ58Z73uwmVIyHlQznkYU+bst0Pt1ltPA0YEhPXXTBGYnRB46fZZqZRhm4V+pX0f7WEggcAYy3Gu/7CZKEtVIuXjZ367pQXU9oyLeUNcaIhcF+oRABFqqZuEAijMbaN8xVuJiUI3S2h/Z0BCZc8Zm8Yo3IB1liBj8w5QUVuwpBtack3jHdqiyu/J71Zo6nC1jzBEP34SoaKQbP4zpnZWeLKWEjzSkSLYubZnWAO5Om9XJSjXaBqgNIoygj++QFdGbl7QJ4j/Ba7FLcwzl0ikmAT9DknBxVoF5q/sicK5HszX/OXhZX8CCnLQVC/NBAty9zT5ARyccoEiRZCEOLpIcQrqdaQxL8DVccJY73VjC19gNG0QdcwvHjaNi6EpxmPEILyiKLgwU2Zfa263PDRDKaIBz9u0bXbOJWd8NGoHEGPgJV3mcKq3ik9hV71F/UL/qtFUZFQjSgx3MczX3OKoxfR7VcpUMyQ1LsnQGQ0WD6nD/RId3peka5iS+/GCZVljlnvXoNk482Lp176PjbJP5K/ySv43zqsdsGTmIq0z3PtMiU6DfRCLFrfR7SxpG+YDItmlRk6TuSv5Qj3cLFk/GHxA6XvzS36uEvxYVr1w8EKQXymCCfzovQH/e5+HG4zPLiEi5DaTN893LriM1xrAopo1AFmOyrovHQfqiYvT6er/LlbWRBZpM/DbKEGCE8PN2wPe4PLcfsRElHaoh+WthA9LrCoYVy4zlITQpsPDk/4KhWi4E7lJXI+3wZI6Bam9/G+ThppB/6SqJRwAB8C0KKa/x2JDC5unPTSPqKXrJy7BE2QGTExk0dqum8xoa6xmXuQc5yxaNlHmFAj1dSe8nH8x+Z5psWPtTctbvlc2C5M98O98vFRIPUiCWhaSStpVXvi5cbfeNkLRxQUczAg29QoXkMXR7bR7fTLZJwR6XKkUngEN3chuhrdKmOcjidsXduxW76ZiHlC5m4KCiCVuNMnK/TzgkKR/LIOHnOwuJCVQ/mXG8hwgYK43lpstyj5F0lpLPAvdmlhDHsjrJFblJ4Y0g0noKpF5wHMlJJCb9Bd1BBI0zKFmA6+iGYqG2sjL157HloUTU0VzLI4b3o6Sxo9XeePfB0n8jrESTNHNQ+GoJZI0khpxN+lMaZAuwGDHMmLmX75DeZ5YEaiEecFdtEd/fxX0aSdtw9s/57gaCg+hu4HSiJpuePXJD0te33Lzux9ZkxkHeYy+XkYOC23dyESLEdZk9xQamPyDXEyHA+WUH/ZMS/x8ZaCa7G9hIuRoubXrjbNtK0Sk9sR5wpJdCgMGwUXuK1fQQMKvkQQzce1VS3wtddV26VRaDK8R22x7LDVDJo0k/PQr378EHtGglP8tGpHqnqwXSupKJmFhz3M1fnkGxYQUhST6lKUytfWoZ4WqGffQpcpQl8svHVuSFLHu1LebQ2EgMrZ1DWWrYjZn7PoeGjpINeriHz+Au+W1Ty2uhxkFAI5NCsUfpPCfptSUNmdhh21p3PrKNBL23W0Zou6/47ZjHqv54R3clpaz4Gs9YnKwlLQ1k4O0b17KdrMUiGiRhoavuQM+lQZazdYSoLa2iUbhIYhjaqFSiFQEFVf1JwupzsoqTYWny4BxV/nUF+uW4OAr+C2Vv0tWr6GaDbhuPjioX/kJ8kHI75DuXJFNV6PXTw4apbs7V3wCdigmQ4NMLufgzyJ3Qvz/2eMkG2UI+sr8WwJNrinGV0jsp8H6kFLv0gxmwN3GdQLJUNhs+StTUgVx8T+MUNz2yvSKKgh4WEnLwQGrFNC2ybNNEDtqQ2aWarUDkPa0mkPhkY0diJ/hWhp+HdhWbWXH5ofLRJh4D5490/y0GIMKnZGWeEZSptWrrZsZRjfZQaSx7iM9XvDIvPHg0QpkFuDC3UIa56dKUWObxZR6E8cjhxDt0ZkdUadB9j/+HdqIPM7ry6T3IcHCBjIgl0GtLQ2CYP/bePTNwt7j2wZGDpojtcD4C+kNMUToeU86KVFKlBz1Kx4zgLFzhxG/DsKU3V2bp1M9LClXapnyq44XcZyClZtngbG5hyvbw4JUMOjQal3NkRz9UEqTi3xCHF7RkLPQr4NNfMdKYgFuuWToiNQKsnPIG51nLVt4wTSPtYj+RK6vgvTDiNi6wwlVhcqtbp47BPa55mJ5p6b2BALPM45YwHwZaz79yq1bouXg8ESuEa+SKXM5UAvGW+Jiiv6BCezltnQcgd03PPvZmps5Z7SHwLlUnmpZZmYxUGRmXVrhNiadALVxdpFyKGZtcHBI03Y/2lBwR5DODKmI4u9FzVjExxOagzQ3W4KhcIQuTF26W5lRjCj80aggi1hdUllNtA3HXd4SWyL8ydrb7dkBE6j3v0EFulaOrJ8FfSuRjVVGpx4d7mOI8TVBxWiVdZsnn8ifnElTvor4EAK3pSGFmlBAV6wxE4YDOSKXVLwis4omur2Z6Ac6bH3EuYVp4wrWoG8ORyp9ytAzWD53MbCIPE9qjoeSTGzxamxzNjkapbHsQwK9xRdIjT95oM1NGiTsCtsz8HlAisMKFkh+HOMfza6u2e8tmVaoOwNcD3rgtwP/t/YyTt1kzE38XD+T73jMXb1YnX3PW0eDC5XoS1bBZ0IqkrrBS74d6iURKRVuVN06LjyFWsL76lcSHTae7UJm5XlsEnhnkyBbodlXj3Mi4Q/ESrAtAb2QXphMzdyE1w4geSilGFccK4Z1tei6fV10egvFjCAFtmmrLqny/8frRWLzYJovumK4B/4D2YXE00ZQg8TxIhqIPGBzlZ7RApOTfgjozYBKpPSBaCQqp2r+cr0v3pjEW28pniBRidX2wg51vaRZGLs1fteApnMgkCI10WpCKXXi41mzEOVCG8TAcjMQ0J8Hzwj1oFesbFIZuRd/z2l7vvGNHJ8GeAkkkyR/hXSbMLULLFZuvBkeelGd33Ixr650p+0H2KF+XtvmMK/qnnsCDX8NDjxL8i7oGAeIrx9wKGkceheGCMEGO23tda8HPVrSjiXzliHXcrKHto6qeIPH066b4czepVNpHXMugwzLyhMh9snKIQQxy3FtfsWJgje/LZGRDlFJIOP0ou3BDESWx0mLQaQ65xf4O2D7YrywsHhIvN2HRvyZc9Kiu+Bn59GH4hg9WipC9rWcGOzkKX3mAv5Z0aFc7HCLYQYsTSj4vtIVW0zo5mJJVP7fCqSzw8sIqnN0IW7DrcpdL9XRbms8AIdf6qGnC5nDP7D9RFcxzo0Y3Aaiezd/rpFgn4Jn8QHtuRjFZjluMbBgh6d4Y3m0yTiaf3Ydim6rUi/Gqo+bLMPNW7qdda5lnmhfiUM/f2laEG1SkLAVK3tN7Wcp4L36txibh8V+5sxIA/QdtI4pZxZ5HBiQMmjddvEzSNRw1kKo/tHHrGhYYKbBar00C50upBBK7dRhpM5dHo4HgFUpNBG2PJAFVotHWjuMiC0gEh0sUYvbN5nkUQQ0kgVq6JwXVaH0WxSEPgXKJKXz+Q2uN1HcJnoUQnsPKMNSV5BPL2KuHKrVCw6h2YBJ6d9Zlt2sIWC+8ubliH7pddbaODsWFmO8nWAME0ws6qjXLd1sFXVipZHk+Nkhwu3FGUeAysfLHkyItfXByY4XTzPwB/x5QlrwsJuNDHtgvk0H62DBtupjczDoWgNW6diAnrn306cfibJAtH++dfGGKMyNDJzQXeAmKTHrkzKrKQIYsPjnlSw+LHvsfTGeWdPb8DnmT82EBx8f5zcmykelCqKK4doxsWSVO6q9xQImoBq+Fie1pTy82rYbR7wTmkSIPvJo6N5FlzT7MuGIYFJPOKaxEytEe3O+bABq/SV3TL+okt4njehdpdsBDyh1fRlcRzPlpXNNeT9KE+UsorMr9bb/rWXliyj4x6NjeYl9n2cYfP2ueisvIfBZdIJHjmsy2rfjzsc/1yMWGJFnI1W7wGBthKan9CbNyR5AJG4QVwuka+ltIgbTGXm80fir5sotsyRv1cDAWos4Wc0mtcZKUblUTsTR1PTREeL7G9EERqkoC4D9PGGwdqYl3nQoSgzNt203NPUEJsbuemg/jcfqGorE0RoXObxOnYI0nDpT3FfrW4fpEYpvEM+NJktvZS1IKIZKxeQH3dLFjejYq9L3eR2pNS5Ca2ZqvoQieWtU3kAN3gaVgveNDzqBqv0KvuWIyCCIaJiAT0AHqcxR9jSzEPJUNKGneJhIEscG7TPLBVEa4nZ/naIEhscsASOihWLo1imOTedQvshyhQQXRKwonBu4usj0UeKXJX5wZJD3Tak/IQgNCTk9NLSKRVfIbIPQTD4RH+G3r2Ig6JGkNdWL9cXkd1inEGn/BNTS3xWELuL6PR5e0TzQEiJOA6XxWoeDpQpTMZRJCjri43MDPPOAmx7FU+waLF/kBvbm4TgBKxO06+t8KwxERaNkkJ3Q+BEHh2l/n5nai7Rxx2s+mqvkLwTsiOIN+jmqfy2F9U/fRJmMu+OnVL7j6EL05GKotWV3Xelx2zec//W+A1tFxb4jX4JKjVAING9dLibT67KDxoDnC4bLvdjEzw3wUnOw89Wgzmn5Rxu7Zb49Xm0IeQPikjUO9yX+lRrvwj5X6FfSEZhIX5CxyrfWSn2SkxVfI/LAYRdxgQc5YQR0siwpEpOXgS3XO4hk9H9PG7YXRk9tOp/VPMf328LkPIftwrfsPTD8O7QZ++SGktS0L4LmWqE3MKlHm/2Q0hjyuLMEvcdKDDpv2xqfiZ7t8uyRCI0a4SK9map0/TDYfWJKSxAZsWgL8dUB9jwcXj7TKhsq1q4r/NSdfvWbugARSJbmNo2sY7Q/lsyZ715l9on9h8ip18VoOq2IEiaxwJAW1qUkKCLOcmWA/NTJJl2v5IuCl4HP0I77Wya3Q3Xv3ihmud4rgkMo+KDBiBG5VuBVYPw77auxd5XZRXAonXchirdVwMRQrKwJXKjiGwlMd9eZyrehJgRKYLS78lZ3ZDUzYGm8hRyFpYRHDffKUF5rm+5Z2Eq/dP2+f+thcVNaQG5I68sWBCnxHaY50uaXTM8FZbau5/vjCTI+F8p5b/d33JusoUKLqZrzNZsahI/gTje+dmP+vCDLQ9QklaC3dGwhMnk8s618Wgr8H6Rv8A3+PoY5VmreHhwvc5qh0lxZitFLab56y44GlcKCOTmoHPjVbuFo1//FeQNJmoDGRMcXeux13hiL7iVOkXcK4Nb76E7dbMBlK4L3FJ3rIUoWbLxNbg6q+t1P4ymsEF430q9QEh9w9Nw+CGshx3A2AySTI7Drcqrxb19QXlBCgnbDCI4iWAOLdRkXEifAYiaLyL5qfQS0jP5lcVeOqsNpnNQy6a6EYk5yToUBJnOuMlCN/6DYO2SiRNTwZ3bcYUgQbQEJzZXM002BtlMjPV0XxDhGQrmviP2fkdcrJQWeffX2nr/4IcZGYz+EtRFphQ3609WihoM+8QsCL9NYD5zkUBcmnV71l6qyuptvTFP7HdjP+yMtrtYZxZ93rxv1fnkSGoTlE0tRux0xdf+THUYrCLMZtgsmhAkJ9Ry37yunIQb9fQ0cLecnTeWvfhJwDf6g/65Be4rbHUGvjEbQiqMyMSFPut//LLxJOM7gp0P6BGotfKojt98GzAY5rxwWwrdoOM7facJG12dw38uVhsgHSlufx+9Xy+00Oz0/tFJmHSoBP+QI784GUrX2tB3fCvxWlY/qhHjB/TvNtbZ9kyN+1LsU/EMlO3/1ab35W5YCKVT/7qSctq0Q5rKfEH48bvvP0Bbbs+XsxlfEEFDflDLCDKpZe4t9zNJAkFcYqjxUvtr2TT5gcFPtnQ/SIYAO4ufXViYqN2vO3V5z5hYmwSBl1MRqDA3YpiBt7iAZbGRMMX7OZXasTYo2cLX/VQMWWEmUgonDPdv7WHued0Xj88cI4heLPy8pkPkfkepjtc/YtR3ejUb9ekmXjPWjxqbV3YNaOnIo6qh5eVmYnPvwBHPKunM+uCINKcBavbIYL3sQHoEtmxG9hIIJ1Qa/5nIF2z80JcomhQnmQfSsRk4MkwY6AIRXw/Q1sws7jagGKHR11iRJzHLzPkLWnEVhLtVD+a/dc79CsBS22xSl90USRQoES3fVgShXeU8mJmXTXXuKcyhCorGRvwYL/2Htgk6juxICdQg1k7eFdQc/SSVdInfDmeNbA8zNw1MqyQ5TGSHZ5k08MjC0jmXOKgddYlCFjjorbGmZ2hBBjTavvZpN5ElROxXYkt1B4tW2UPfYgQwiMWMh0jxAqQF8VF3KjN8u560gnklF8ufEQfi+YeZZWiM5GEqjQMXfpv2q1M3m/2PgsmZX0+e7goYfeMa4YXPT3rL5jv2keKZQZSh9rU4V6zOfQCaJH23lqb+De8vM9F8vNN3xWYZSlgpnQWv3e/mhug24dfP9ON/ZZ+lAcmsZqF0dzLBoqioDHMso4t5MXRHHs80l4NoDAVP+Pti3YABZYs7fIBQf0WrREIKkM9jZYjDjygZ/hWC9UE2Q4gM9cucfDf4T4SKO8lwRcxY74v+iq/ht6/v3jFIpPbjWEsMnG2qOdLLeHlLcVeFnkcLOxnD0dUzwvWd7PLx8ICsyuJ+hytRF9wrjk1u+mK0M7afj++C7RVbevEcjBX1r/zvdTIv5xh79uwFdPBYokTfLtpk1ppNX4AqwPt+G7TcabqYbdUwONMYwqTTx4APNNH5zW1SrR5xrCvLs49st2/JUodAPdl1FHH8YAcLYIb63HJBDrYu8mWHV8YsAyDbmoDyxi4MlhGAXBR87wyOg5DVBbQmdd9zRT/1MV06C6lVZiRdz8pk3jItDFp3A19urlm5s0pKufWl3/qtVWVyM7v4wA5vsL4ZANnKhgk/K2GUE+6AyLBnmKK22nDin5rlhQ7eoLgT2kipUM7lzWCkg1MrY8GUJMVzet8NFBr6NzUyKXf/m2/WgeKf7HSWRHm2lqdvxfiXk7ItVxQu1EnDpYqb79f5cL2VCtk0wSZAtQgSemwEZ9QjIZgjucEd5/CNlATPL27TrUjWn6TLZksbkJtVZOYmAWdD0XOl+qZtLJKsPXxiiGtarJmnGf9CK8OPt502+dbsE0OyzZz68nlg+FYhcMcl8nfeMiuTlF4/XYj8VY3WkDW0FoXHa1uWDsG/hejJ15fl9K8kOuSB66k6ji7oM2ahd2sn3GNKgB61eI4iLM9ORVYwzGLTig9Ryb2TmNoxQR47AdeJXAHXhw0mT3rX2yaRFn73bzQcRYKBTl1yEBe4F+cc1ZZN2C0axEO1wkfNPfD+FyrxptvgeZd4s6waLonu21wUCWMumuFP9EsixevVLwZWx23Nstw7usC0kDuMNVSrCqHniFQx2ualjrB4Raq+5VHLzPn2/BCmzjrGXxWJGkqJ68gLFcHp1v/Yr9RkOdF9CuLWX9Um72uJQ9WCcr433DThlcm5YygXxSmrwCxRfXp44AMxeo1DlCSJlg9eZeBE+qJQdH0c8pMhPTebkW8ji0Ni2N4eLu77m/P6+A+yD7ysN+l+B8DdzZrqo2WW/0Lk2B4x908TEpezbwBFghxcMMwTaXutMCYDOL3/5OsCaW1Wk0xF+k6oj1M/bqrvM5Kb846tC7qY2R9qp4mFmD0GSWXw9RJbrYBN8vW/bvwiIxCnKW0TKZorvfoJIQ7H0O2uQQmvy0eIq6Yf9DmR87DdTZKJRscjsxCm90d3s3SUrrRaAzzvWX6FH+Z2A7Wd+YKeW/fVHd/J6SwOQIDoUPG7YyYovST0O5NF/tF0O004+i+e//hV+q4u3xdnTHH4IikxJAbMtjAoFMnJ1t/8/KS+8tfpWz74R0hW23sb3Gp3FnkSk6JGxbuCZCVaSqyDrzEq33EENG4Mrs/UFWVdm5/ajxeRhjnLYNTO+7OYuSF6m3Rbp47GojqCdBVTxNk+bRVf4mCfbnn6Icq7pzV8UN1MFhf8qdSRUxZk7bFsCwnFrdXC+Ssk+jfCg1VhzMC7xMf0G8tdLf/r/N73iV0tWvm1E8U13RQZaRkx1kgmJKNSHQIJfb7ZfqYOBBvTk1FOBVI3BKiciLN1Ex2EcuoNYuikTqoEMLwKR0jMk/e5L3N2d0zUvlmkhOqR2MwvbWxOdHTOWJh/SmrUZyp2kEF4DoTTV52FkPPslogqR2g7LOkwHzjOteT86OND3J23bQF3EnsK6WyrXwmwBBBGy8e8+YHBeNJFvmnetkWDLOGbApcvlsPL4X3uU7TFuRNeh0PBlrCdpCZojCkYLEGPnls8nSkrJwBc36gydx7rs9bwCNO9wQWBUsILKUSFeyOGWlx0A6JBM0Gaca6YBp1WtC4raVNRXhYAlFRFiDAH0S0ZmiWRkcVcaCiapZAm7KwDMevmqKgMAGolQnApirm1sPtAqUIWuYNppK8I6ByIcpjgUVnmc1uVXsDi10Lo+VlPyFGUtNdIvrpyzW1VK5iy/xUX3kHzjurzK0if3O7AoW73i/gvQZLEC7vWa6tDuwN3kaXINNJhsVoQmzbtESOHXGR+pOQ6kYEixXMbLDX/9HK2riSMzgrcYB+0zSIKbPdO+wDEficWNMlrsfYKTkLrSrgQPG7/qdTZUU3SHy4/ZFRx/4HOcKQX2H/Oq2e5P8x/MYcssTe5S1f/mzvBcov9TNAfYs2/273FgXh6d4M0eCcZI8DaIUTrloJp7EQBXzeTv2ef7/Vf9C9N8ja1uHAHOicp+3QpwBVGt10RHcAHu1sQCCAXDDjjBfjVorLrtUE2O/tKDtGVrkYArAE7NguQS3qsH+Us0tDAufafOcK3BgUaFZisAsPvXxcEAMAeml+eRMOvWNb3mPPPwq2stKNydmOmnrhgHVHLUvFa7rfl2yO0RYqUQv1vajmv1fTE9ySiMrxRka//cpcQZQCxO6mtHuvvqVnYGQyFoeOPT9v1RMXA7ANMcL7UPqvDVOPyTvSXlPNXPZgoOEEDtbswDY7DTiFjHHi/C77X8Iuc2ptjT9DpWu+jqfG9KaCmc9b531OBFEHsBtSqMDo5t6Gz52RLAmOHE2v/ovVbD1YRVSx153qd4a3skhvfhhXP4Ra3AroITugsXPJ43QxcnGX6rCjjUUBGFoqjN1benomVvz/2eYbAqbQTD8BkgfK1EoGsHbHCI0Bm2zGHp2JOmz9Y3Vncw2W46HgcuKj5ED/3yd7uGcP4ab/FVC8vtwkz/QsWADCMCQNb4X7mIGP1FfDadAGyL9inz1p2IsTyVncF+/O7h8v7AsKj+8jslBpGk+kVWzHoV/Gl6j6Mt3lGGjw39NQbxxlpW3gALic/KemEH8M/wvadGFxd13VlkXz291s8Z37FMCJS/3czVapoge1XW3soYmPt1PLt/lh1KyQp7Vl3MAwdSSI4ED3ZEBIwa70BeUsx64jumD9i04g2o/Ez+0/a1gQgRR4DfxLY7/ncQqyLYvwK1lFa6SbLiN8ldugPvEgqhB93Baap3pWXcDNQtUQNalico8iEWCE3q/uHFUMrYOTKS1xQIIcEuVxwB92KfS6q7ewAkv2WAD48ZEIiAt9FUlex2sqqDuQUk9JefyxXkWAWdPSLNr0vI5RMZrJOWR4nvEPchr8k/O/iblSzxb2KO5JubkBs9ubAx+1MBkDwQ43w7bj9NBN+N0MO6s059l1ZvwqkO8yFC/b6VSU0se64qAs0FLLMo0Y8k5ocbIs28LP/rkhaQyIzgJx7CLABBlgkeOEEDEOCbw9R3HYo22DXvc4U67Vl0dXpzmLe0r0JEi1rqA4567JEtSEsozxaIvieGp889jV+Uo/PQdOxQ+ENIYGA6RibT/UmxdAG2rp3Xk82ensLdWoSp9DXT18XU84wThKnyr3Y2ROoh3zUBmRUo24cyKixh6Kne1a3oq0XRU+iVaaN8muazAxcPpUM26OX7N+8vZoj1gEnx6IqOhZDQFLvvTsHe4OkqdZCJAdUBkc+mRQHUVcTVKPrlbDSg4dNixkOQEU/jF8c3EO3yoKeNQW8uAMRCV0LXh2BVoV8tIyIb27mCi73hXell+gwRkuMa3RUvbaF7ucO0J77CP0eSv7tCPQ7CnGHDwBMkGICfc3CPHE9u0QIuf2v+ueSOTdJlLsPEzlk8mmsSLrf2iJREDkedQ+Tl/MyOFjrmawFyNQGolFpGylwvgwV1kxeBrAfS609OIwKrbswOsfC5kKsp1ILsglfyqRhdEiGegEHR54DMzk1V93+/rLRgz/MD9dD0oV9WwgCfaB7hasFOEi545IEdw1lnT1bXS7b+hW/1MUiK2LISTk7dgGoIc2JK80xfj2O58haZIKhG903FrTzckb0EhBlwo8odK1KEO5lhNZqimsDxs/ChmXN+H8AIwLarOLkYE/f1T7vin/QxBwOemFQvaaDGhRJG+aZ6u2E5rTF2GFTOMm17TFs4hMBAApr2dFHL8vAH+DYXCPQd6oVdGTSa2OUYMa390Gz5jlajDPaXKV4xijHIhSBRAiEIuB0LcWk3NYUG3gyeZkgDNmuShNIIDfqjZlwHvaB3HqJLTFDmHNg8DOzaf5i2bUZVfVTIrGuX6r9f4tzXxOUFw8a4sM5NKYbZi9JHMLDdGz47UbIfB4Ce4Ks8xeyibfB+nKAdT1pWWgTrpC1Etjiufs8DNw8U65/VpXHeNdOprVA+6UTVgzwj6ZBeHhr8/F5mk2GMiIBd0F0gGoWFBOuIvjeCMPnPLMBVA1FQANYQlJZDO8iyIyhHWBLgxPNsO2Wm6dRbpcGUySYpBDSOVaPx9YP5egYKU6EO8ZIrUkamibcOkMv1NmQ7r5HI2qfN8TNhZnLdCFUxMEicVi2CgcDnKW67b5fkTxn0wpQgcP+uWMY6B7uSnI5XUmOjiyOd53DBHIeEmllM2apcp5JDOTfMjzH5y3o2cDqSetPVud98GeSY7mcVJvgt0be4Hi+FJ0VFDRuR0ylrBS0o+3IynxiQNLLV6ggEwyke95WQe0pQrxM7Y0Zky5j/v6csrP3/2I8szYPxLNKtKSboAcTMGcC88hNM7ZZkSIAjR2/af1vjGpWPW7XUaX8RJivpXxsVPqSYwIfGnGw5CbTpsCVBIivLJr4TzkAanYowV1vgHyEmJHmfnRy67muH4JYEcGgn3uN4CBRy/EweOFU+NtO9BFbyw6uZdzQAbMT3kzfvUXYAdGZSrHuA4tN1u5Jxp23zXwTZ1WvJa3ZYRwqrVpkH2NvCckDlO5pWe96WP9cYoBkAt+CrF73rGE3uk08I8cafSN8ELHMfehfR0v0ZMvaskNIomIJeFxez9J5f1gv0j9p9NU6g0UT6qP/bfR6z+kW9exRrymqGoDd0lsoH38phKPF44NW497DIxbfbTEJYEVwlRdUN07PZIvQRELZVopfBiUYNvb99CrNJVVPERNYfpqsU7NrmHbI8HbawL9DI1o0c69KZQlDPOcYbhp9WuKZTWVLMmxJq4q5nW+pHLdFqIkOWtqU37WUUAdlf0EIylLfWd2XZTWUlUitORnmGigh/CILV9g9nKMZwTwyz0HB++t5/x4Dqf8RL1Hr8KNOGtMSDd+Z/N8SwgV/6Ucp47Pd1i+W6D0WtLWoFHbSS7KqI9xiGJ/C1+ia52hZ+63v+vqWFdCyIe6jmbZgBaoz5roHNjxb6sDvMu1rc+6tCm+dx84krPGlP71KkO/xFnCkkeLwPMYLRXmTJmriXe15AxhlGKsZRTx2fp8w5wyhqjypnouYwgIDEeBPmGbrp+augb4k4kcKKCVD0zw9/AEZVhHf1TD+xyDgXsv+yWxUgujrdi0kkzFf0F1xOjCCM/ZX+JQX6XHeY98DybfZQWLTdp5SNHTYS66f87n4c66dDT48NgZ2OTBp/8NMXhSCV2vhbr2w5ALyVJbCw7eCWd1Krd5t3pLJ6gqn+hGUWRGulYYYHAHWMOF0Vq5Ez3KiiDj3hoh/2GhcMzsXu2KVwZP6dmuHrJoYBJLbVgWZH5ZPf/zjYPLqPf5HYio97CgxxEqC9r58aLJUnqFsLrXzdtFcUqZXNrQr4CAx0jtR5ZSW3n9lu+lEjtV4A/qCxFarhkY5Jd1DLxjOMnxdZ7/D1c8mv+jbwtYvfAX5GE1nU72Vf0G/JMolEz/PNI0UqqKx88HK9eebNDzSQ0l6VcZgbKTCeFaBH3jQ/XG3I3fLJyKWERCbt/saZp9KLz+R5L7mJVuxBEB+3I08DsOIqGezH6eUsSy+0to98wjtLw9wXAd3nut9/CBdHoCawxD2miC3nbK5dlb8TV9RzCWyihKkLoqcFKshRkX0Ch3Q6S8P/jmbM12MGX2+Ul3Wbgk8Hj79BBawbHlpAGjxngyb6RYfZKn373LB3OF9BNOD4HCTxQr+338m+IyO87YJB51Gucg8fJflRbcUVrOT4ryxK2uXdJTp6LtEbhCk+UyoBs4xmRZbzK0qS6A9NEXrChRgO+fG2xf4vobZj7WXH232hBvtoo+TUnwazj28A1CFsUvbcmv5dt+zURpYBfuwtSfEaR9gqt0gnfqA3k06teaLlIM82sf11Qy6aKQrziG4sWgWPTACHSBVoPMT1jDirINTn1MfpJ4/NyxHCJvSFkuNUkr5A5l0mPonGyYR6qnOB+G+y64AxmcT26uvN7Jipa3KpO3rJuER8c4tjDa734Mm+qFhPhlqmMmPon7l5guamsFkq+esMFAR+3IzeF/XZCC9gHhSc0g0pqF8zPV5tK9xqh6C2pcSO8Gxxj+v37KnXTv+dkzKjg0SybsVS7aBAv/ZMJjgUSNtoqxk4ZInMpZp7DLPToWkvS8IZxgMI71AUITVDHfY6IslcN6Chv1YHdnO0e630qT5Z2EtuGFf21WysDWXBtZSpVW0l9X6IRKQ6no+LLMtphJzvvhuQGozp5a5YEDTaP2w6EqAaou478TxCgJL48uCzKLIyyE/vbr75oDu6LFw/3AIvLEjk9c5Ykas8a81v0K4kRSiDUlX5szSp9BbmbwRvYBJZOjG/P68JGhum0F3pH5dkWYnNK0M8ulAM/1cAcykLbvllLITsbjIjf0JqBREzJVb2DTWu/w0jAETYOXveouaeN6T3ujrj9yWiqEdabIRbOSqtxVf7EAMBXtf35y1bnFWgsbY76Dz3E5llxeBLHMpbTZeeBaLNLGCd1IkT+cq1efVZeNFIJ3jtCsFebA24LZcky3HGLrP6j/YHAw/VxDnRlIrUzAD9vUOO3eRvdeYPGkik1Jc2obZ7/wHi8fATgqvsvQZltUHiMgbN993OO71/UhYk/6IDmkd1RbbVC4xstlHwPRD9ayy2X6ozmJ0/8xjg0uTqXCDUWkTQP+X3vt59EvOpI55BDp2q74HJyuo9dpE84coDPh9UjHiAcz981eE3WkqCX8EKQr2m9YcHb69VChf0T+Q9B4ppvNhpV10nrdga3VGZa11h7AXHv7cpT4mQkMjPgZE7OQQuc3X5uaShhyYBNznrkILh2ZChCUKMmho7IbWmVaiS4sO+Mxxlh19x8iJ1T+X88GZVWLbng0O4wKyVDoDF7dSncAK4mR73Ly/9FLWem0KqyARm+NbPLQnTepsslze2vixWmbLB+v+FfH7ZQkqT7tnMVV0olt/wQ58OjlAKJSjW8RV/KCW68UyJdTAxbChmCc0U9xq0Hx7NXLtk6re544Qbsz45ck3nybOF4FMAlA66L7Oog11ykxeGTqgKWsIaoGkHuh+Ze+KzU9ILS8SLzzr5LgQSPWtEwBqqvElWJY7ADWLaV2JRaJODSndixyGBzv9QiWgOZZaSb7V1vKkJd/h0vEUllNai5cIDkG+fLmqk5+GmZD4nlCKoUI+ynrCBljRK7kCaclUA4mUuAcaaN3JXjPM5Vsat7pcwnwGbPO7yay1WZm/qWMNcWtERNC4g8bC3dEpTCNavmOvqNL2symcwWBEecNiZejaYBF9yNSxFht6MzC5/LOhmf1Kv0M562O+xC5WEdL2yE5bjoEdRNYuIDdDlz2GzB5ZGELf5nFpkAurhh273arATn6Y2f2Jal9Kkn/XjWOittkmD2UZg7mAb6QYEiatZFieWaDW/ldVtUqud/R8V/BBAH2Ai9BT0tXiosuDQ2u/kCPqwInfZg+ugz6qocX037ucV5cZHixJdtWO0xBHcj2rxPqum7U1b/kFnds8vjlZTdjwKyEuPv94pHhjGVR46hhflS96SYKGdgYoIszjIkP2bCgysg3etqFXmUDzr4kd5ONo8gQg79P9vzFpXFQqN4t5IOZsg5bZ7bcbUV1/dsSGxYmsuaFl0I15Us3TNUM9sInaiLlylicsSGfc8qJD15RCOuNtqMHitZaCQRcgYmA+GFXAK8KXFRGt9g4emsGVKtSC3N2nODJb97OluSmnkLl6sGRn8Qmk73WFBPZyPKGXewA3ov+1pS9YqEZQp9E0MqQLtdb87WJTGAJmm5plVxK5nf/eKURnd5589aKVkyfeCFGvajDee7rQQGnuVWhoe7ga+A7hh0/TQumj1sP1Zjjevbkc3PbrFB4L5ghCbJzRO+1hnathlV/gcOPshztnxHaYGGlKYF2P1Xt4VBtVNfcnVN4dIM926154teI/8LEnUBqqf3IEJZHbEnH82WGipsDXVBP8oKQkbDirfqW0KDuvzSrkdkuaSO1LtTNAoxzAQJeQQXKns9CAfuDLlSVbRJH3mPDBTTjPBHJrH6wdwYp3y5ZDmPlvnnI651CA1lg+v+d7AmulkV8QYSZkOsdtuZu/grVUL6zJ7dJpOSn5I7Gn2CqPaHisEZmyi8d0Lgh6DeDbqjrdNg/REhlNrKzEH+iRwcUVN/JwnNbM8fFTuk5yWrKMGh+MeJBOFyWtp7x6XiP/SbHb/HuUkU3UH5DrosQrSYtS0ywSXlGPjQ3on6bTG40VSGPg7cRu2xbrxYMf+IuZ2wW6I0vvswzPKsoxg49J7vXq49Uo+JVpu2HQy/G3nMr8H/q93Hz51ThjvmveKAi/235XuLMeBLhHgL7Kn/WVUrASq9xSIP54u47OyRXMB1eFisqFvwP9ILGFCgJB407DpCJ8Fx8sdNA/HLJ865mlW1Z6oUdGbSPy4LGEgWdBBua4gBZlauMLkdNdaDYl8PiygIVJVa1op28Y3onZR4C2OV0Ag2qX/IrgCmv3NZ2PpbdqLQLwTKnsQp13uyR+QikNjY9qI7FPJ2mvxozHiYgxCc7wOZFEk1UrjwIwZqZYYdAjI6UrBpu7clI0076Cg2qe2YE46gadSWS/2pvIvqH3aBe8fscWwVgUzI10WAVhT98/GvE9BxUFS/JIfhuolNRHtz1AM/7nSRYnJVtYP2iqxkxvu+GPFlTAaUASa9E7HWlW1ERcVtIEdkkeDO61pfyzu3bMfe8Gmsd6uwt2ubc97/3kzDtQPmGjAXCpL2tcvFyrTdLEjqlstj+8Bn5B/9aLgGi9QDtnmpKBqgN/defLY7Rgj0ZfVJmF8l2GX6LMLu0zyHPo1BHL0+OFJnHqkKtZct4jI/1QDh9GENr9J+5aSuZNCQ0ex0OV2Taw3yjlabF5zl54TcrGAYMsft09Rmrqk2d9DAJHXITKv1IBcM0mv0Fmd3Kft12RavqFQOvA2BquqQ/KTIAHFfqmEjWamM0sCUqkExBcgto8Wdzf91h1etHQEBPE5DD5pryvcb0HNSsY8qEKGen/PqyI9HvEBOhqSnIl24Q3QuwQsfkQ+QGWus4WAe94E+TfCJenRqrlkxhQh17dNomjT908X2WueAvLW3VirForgXab0ZsW0FZX7c4g/4NLOfcw4TPn52PWGh+jH7N0zU8qygMgiqjZGxMD+XwvcUMc7BDtPtxmCrRFXLErss+V1wkCj26llRiw+DhQGxfIETXEdInF998yuZNl8bC7lwDuSnW4BAyW6cO5RdF1zW1DLNsQl+uGTro6oGQTxr6ua9OVjpLdOC+JwupBpa+pG3UYmxan5Y60F6yxqGk3iZm84agoOYaD4dutUG3Q9OIcRTTk87hzx9LdgFdr9R9Rjfj50t7QvUSWm4ZD42fPh/J60gerd5vDWTHq8+QMvIVwZ/lyPb7JdlqEaLClmIpnK+tVQ2DLv9NOov+VwOADI3gT8QaN+BZWiFiLd9HscDMUcE3CUD5ohAl86UG42lEeKA/9t4cQqs0RoWbqTJLxJ70C2TK3Pj8deQgR9oda3NEaIuI899vrSMlxDspedabhOm+KqgOOzlov9A0A37OCklp+38+VIIb3MwUtA3ZDaUbf7L2e8WcciAm2iGV71tUIOlbHfKkzgLk/GCpruoMYBwhPn3f+6KCLWk3D/jjEsO6B3WZdLBlLyphUJklLT5o+3+YBxsF3E7aG8PruldgFaEmGTqdL5vL8A56/QzmXx47i58C8kXURWBikRsutxIj5hCK2XWgT+N+xLn0HpJo3CMRNZx7MuWFgEe6yKvmZ/qxjfrnGKm280Bdf8HXXjNIMS6ajDcf1ubH0V33Ah2mXYG/FDY4zGlavVBH75YcQJ37/c5i+63sKZCLzjRSZyRmS4dufuEs4bWdVsIPkILFkDg8mz2bGCMOnuPSHBZVTxIt2YZ2oJjQryMPqSuIVfv/nHF7VrHi5LGWXtFPe+Es6pCDuD2DUeOJ2brg+jsiM30r1I2sIamSHcOaUoglJd37DPi93QSfGtreA+YOsDiJp1rVw3dAa0CW0WOXxSASkcU41uhZEfpYOdUbSJej/2InYfv0dW74zXWcvWsMiSbDEfzHjPtbaXgG322orR0OUMHMIwrkMDgkwp2SWk1RVS3OJc79ezBnEqWcA8fYBNOSq9e1HIC4KFlu6iv+7zMApyIXxpCiJrjhignzWU/2z1PV21CTqL6gp9Nxkl5WZHITyh/sAMbogVcYOm19IW12FtJ51xhHFiwOmqebMlMwojz8I51EnN5JJ6gvYxRKbNpPVfxWMLVY8J0OPdsQBhq3BdJugP6Rlau2Kh6StR3gJh/5TZ23Rb4VfnPEfveQIRavXOYF9699yPJehQrfQh1A9slEdKXij+DI4+5g6GwadicPL2Ti8C0iaPc452je8IUsxzQFvljrshI8Jk/6/PPM/7G6go7LwlBMAWYHWMdzmMcw5RO43jWPHkrqj8HwN4ENIn2yg42GI/ay17+Q+Pm7cMc2GfeLHTvCsmV2f1ptLQziuHLE+mm1idpNAqOyPDWtMMMbqBY+daDE+VvnVyqLhpLA6WS80z5FsJEhk2AaXYxa2gzi3V3EMpOCFSOzCvPJPbltbtjt1NoglQ70EleeA5HtrJV5slY0/PaFJBho3kUTnFe3fbspwPfFXgXV51r9JE8y021cKV8Tl0vejdlPlaAagmaPwNz1wT5jRVXci77FjsxjSoW8JuS+horXNdl/2X7Gd7Srk4ubp8YKCZe0Z0Y/ChBWrIs9JBbCkh7K2KV4+YKn/+kNYA4jBaogstE0YmX2QUUJ9FM0t9si+1SEBefNzNiaI3HQkhavlcv7sZQCgs5pue5wmZLj4r2W+1r2CvY6dkAKiVMqS5MGeawoK7BpPf7C+K0wE+yyceQffPCggPbVM91ZW6s5J+aw02AFAGM8d3SoYMPWnwz7/eTYS+gaHPQC9cfLpJD5h4+VMr5k1UIKrsUCvIS1SM1Vs9D0UX5g22gRKx0NzTlv7xgb1tcksg5I/1uguDtfovUrg1jLEY3s66GcbGUyBfCROzBxHU05cFOPBB7Huqmy9yuxLvYq5SYZGKByj5l05kr9BHXMNOZuHHWFZvLNNQGsbYNsZOluOJOoSeLqOqJ9Rl1yWlSz21kHSYJjXXK3rU0qSIHs/MipB/F8x3mm7V7sOE9Q/jXMJadrCxokdKDP4IvHJhULSuPaFaPnqc+5/oexinWDQrbgP2GA3HqPeBrm0LSohbIY20A0g7byX8oSXO3jl+H3/8hp8SFCU6Dk0r3qm03znJEazEHZj6hO/YNZz3faFBP24eutz+26oiLFlZ7AuGX/kydi17GG5+GIVPtLTYEogyQ+/EnZmhg+xkToZG9YWitjoc8IOj0mSel7rGToiwtbjbJf/L0p+vB36XX3CkpNyPHrRrvIU5ka/stTXiVVVW5X2TluzeLa+Krfn/BfSAXoO24WMr4p/teTIypQEWn/EA2Mb/mWujVhH7IiIwGEQ0PAnGOtNPBZzvmNFctzZZxg3MNgXuZsgV9giX4jSs+xVH2S8zEDrgoqf7Md7Tyw7fp5hIgODIvxA8w5ABXXHj6cxzbHfTVla/cnnWI5kZtrGgXcCIP72M8+TUV3cNO16tT/Td+yavNEUA+WxGeEQEXC/1t0351yfWcW6YBMHnMz8uzN5y5aHUsPBngboruLNozLWwRwUMzh+cJ/ceSPByDWXf/jrpNPJ4kYl3+ePy0y3u1GY+55xCD28xrneXq31Rzyh277UkAd6SxDjysxS8O/0T1hJQ5qBK+Qndry/QFz2Fruhggr/81/SgmdKcjUDcYw45WTCiByb9NtfftPCj02rK8AQffGW0qThNeIuFg25s233MU1npNtKJHRdolkpQBgfXu7R+oTbpDRwLZGiNX7LEX7KEJw+FClYzYlQrTffs+a0ggf+CpgCl0igPeGnb2yNgphYQ9lJfd85u4SQSx0ldY2jvb4vkDrg2QF2hXnZKKTgdY1KE60IEjptpgzGe1g3SRRrs/vgDSS3sSaO9xfySqrL3ZyH/Ch16XYkcGU5LaqPJ0M9RpljiMqcENHx4S7dmhtxi3vynGweNEV7RYMGL/0538lRf6+mL1tR70oBRXTANKQSJGMtz7YmK2Zf3ej8PHP0uSOdr30EtbWb1dp0GP5MpcpFs8FIqTzLlOw+G0LC0UOyLVgFVll12HJ/ncchnSMjk2LM+h34P882qwI5G0DiycAGy7sRL6Rw4mR1aKweCUgl6ls+iehg0tgehkktr1TeuEiFyRW/5yRqaZwisQOQur+4TptQNFXb1nXWxfL/2DZJ542HDjF4TnAGSXX59G4iN90HBL9UrX/o3l0vvfuqeG8oETyjGptJkV9RgNdcXfgIEqu/xuUkZBymbqflWopaCh3brS6JB4q4Ewd+6enDKwg9HelprdgIeD41oJewxTnNbQId5pNlhFpBznuuC+VTO5Y/n+qkV/s6ZLsj9/ZbRojOBjwkjlCisYM7TAWuTtaWohluyMzo08sb+iFp20MEVQp//C6FfV96Sd/MigbA5CxHzswlZusjOwfYur7uMuHLiICprsRuuDfjEqPytixP+qtKk6+MhvMeO8L/uylLQav3GMwlJswkOuF8Tj0cOgQigfIt1LPle18mlaDc3nyYw5mLdN+Bbd9lTeBJTAhy9VD/clu42A4YX/2IU3OoRfUenGFS7BuiWIvKcptqmCg2BR0m9Wn+U20OXvf0rMvOObVXXOkIdQBiIyn7TzXORkGzIrusORlgmmnjp7ouMQTqPXwesTgFIkQlaP+yWHcI9Pu9XEgjZAComRrWkNOhlkvuEFHhbL7iA5C3kzOz0Q8rw0izSEsvN9bROwOolwiO9gKT5eu7TpVzejqHK30v2Mh6RvpdTrqjo5v2vvfR8gKQf40Mq6Es3QraC1FMi6qsIB7oW11oR6N3MmTwF1us4cGzsOxboB5NzW3vLlmAPLnKuvbigh5XI71x0S2RwPuK4eSoqVHSadJqcFB+0kMzEN+ldFHoMN9bxFqAZ7tgp1MCrM335TKJhHyt29qY5SZZJ8wq9/okopiEB6hQT4wzcUEtyU4TEVy6oUuhT8nnNupWgbhiyW6/PrMd5XcTMDSeeA+QjC/0wiCEHRvBtci7kLrMJElXzK4W/vfh0aks/vyZZfWl6SrYeMgyIR9CqTVHFDquyqWuuIYbKqAkiqvQcJgyWacdyJSnYNnLHIMi6LYln9Bzpkg5v3kIlNmEk7ChVvkSABE+V2vNUXplbI2nA9Uqe6wd/o/Xac7VNWADOEJS1kHYkVC/KtrHSyfzYVnU4Iybt6v+TBzT0PgGlIwWHWeXb5+ffjjzn05YeeHNDlLvCIFxvz2c70+YgY3Q+/425isSV9ZwxulLxPXrGulBuHhLBv1DnkKTolhrBnc57C9CaGTXfuQcPoJcbTDxGkT/SHZ6sHf7AI4mvvEcHrNyesBkStFfr3M4pi/uTeTO8bYb2O/106Bgzo52kwcRxNBVt7ZDmOfYvtr3v0ADFqQfUvwdn8W7jSLJsCEdhAs7P3a+U7leHCvb38eYG+CxqoMZjuk3tQ7S/BmJ2m0CzyrM9lFADmJhMVy2Pm1TDtUzN3Gz2ouu+TJ8TuO16MhIvT2NE3fCC5c7Xh9NnSTNmcjl2pUY/9p1mraz5CXfbb5P4W8ZRymcRoueTtFzhJMjqNISeamLfqDi3o92xL3pIv2LayjixkIdcsXzsXzWJJitku/m3KrnKiCLTd3LMzE64os3ch/d0+KnH4DRlJVQDFkx82AtOR19FuhixGnS/PoSq4j5UT/LSJhzvv5okjWK3v03qm6mppwjEcwcGmMFmUoyhjBmpjDqg7gE5Tk5lTRw2SIVsWUqHXNQCsmS5fPJ6LcMUD7imLzYo/+yHofNtIYAY+6tB+x60wF0oTj8f38GzCGUKcIq1kRQE+m/jkK6egWPOxZLhPKCj9cQ4vZ6uBjlP1zBXeA56oNYdZX5ZLOwbFskjUnAhkZUmGpJuf+dpu5GEVGv/YMVlU+p2C2XjxvpmFjm4kkJk90PO1jE0N7KnVWVmVNPXxW7DQ+LXlS1N79REuCB2mL/sYskMRMwLjgQfCGHjvpe3EoUU+tvNFZw7H0QGyd/KMvxd6cc9OgIUMCUoDOEYVLnUK5KOR7sU28urcPWgAfMZ51dIsswwZyDz+Hvrf4GPaUT3bqPmhhCRc1cGANU0N6Zm3ab//nv8RexxRv9nm7jLZgLseksVRUxr8kwNblYfIpFyIFTY22JjdYv5fT2m+5GS84w3fQL+lj1z71I+DjkI4twUmK9c23ckmJqSpTBlJMkJJ+Vje664Wy+snKYo3oZCvEJsgf5YriW2WSj4sTKddh4hHtFB2sou48cMgMnkevqSRRtoXHVCdwMsMeP+lBrjH7WGIaa3A7DVEvpkLBK8rWidbOK0+rDmys0eFnl1eAYt42+/7lQ0UJXozRzcSfhhQ2XN5Rw6fILm33MjqjemTUKPMR3MwX7vH1q8kz1yeUvS8f/XMTictkrxHDRfkxys7C0dDK6JnhuVALAO2nQGyIGoB/joy2t915AeRU8RwPz0IqT0fTc51uXvQbLmlUyHJJwnI3AV5hKDkrEdam7J+5wfJQV+EbFF0hy+Q6Es7GkJkFoIKaC/3Xm6HQhZhXZUyjLKKWho42TA7w7lkRFn6LQCzNtmgoh5TsPyjzr5PnIFyYM6GPzxGare6jk+8U4PTqlypzjStiEI8TwxG9ggXH1vVPobXpjVR92figxhIC7YdR9lL6e2Erw9tekvyQuRVUSaTEOxOFjyVMMbYINHNuWTz5sEZ3t1Lyy5JpaOl1dNhpqFhtpRQSzDoNuVbgfqDRrQ5n6TPkP+Vj2Iu3BWSYbntjfyEnB3KM1TNFqjAZI1syD4WCkzu5dvCPjBNRJ48wGQklmeas64mToopg3ehHeCVXKwL3nqtoE3dk+OXoCNurumEQyJtgGq5Et8N+kaWUjatI6uJ6x3DnxOLtrynhP+7wRBYmYEWT86eHEN6Yc6f8prj1eRUe6dyQZh9spZdGcU/TmzlrEE5XcEX3EJVb2ik9J3U2DtbN9mgrJYel6N1C8TBJCzDvYNDOI0OaBrBmB2EJ7B1Y1iJhwEHRs6nVDWMytQa9QxIjCaMYQqZYcHK44iNVUhCDZK6pgckCnXqJf7z+KRewqG44Jv2AUoca9XyKpKbLHfpS2viaPjo2TDBkbL/GLkeeCH75moAovHO7MMOBSfFpfaglCqrMvCbyUSs5o6/gXZgs6InAjPxhoDbW6NUbLxTGtiiRA1/UFMIFh84bBNlPYwi4IwdtXHXdMpMiKx0uDx7Fjef4O6H4JJ54JV6NaqDFSm5I7Ez9qSVKthx0VOO3y3+sFHBZlkWozqFDWGSC8AO30xJMURMTEUv76+lJ7I0yjnp+S0pDiKU2Kt5gJCWjEe6dBcBS/RUORVV/rcWC1V2TvudFJo3C7n4OaxHS7Vlovi1fVtXDhZXeFXtgRRY1rCQJSWZEvZNn1Ik0VqaIig7fRdKoUCUjbc+cJ9e2bVIzrmph5LuyDfYT63YrwyjK2vfxBOlPczJ9Hts8FyYqHRsPgZKTiEyaxHQaDkngxHKgDUfCIiqu8tveROpjXFrKg+mlkisCZ2XmBCAAGcfJ+A5UON1b+/GELQQJKor2hThdxkKsbjnxENLrG+8K9X+iGe+3trrdmE9RspxPFcDRlTKD9sbrwCOJzF8qJ42oGctZe9vEYR1SOxBie2kCc9iNT36dpcW+cwl08eTun40qIwJSeaSqO4c53L2P6A6DTqD3RH4RSTsjhgK67GUYlSbo9qICB8zOalq9fQV/GBVXOqfxeH5FdTqskgvHPvgFYNG1Di1Nd/azRIUuJ7DcfzbtsezHmYeoXYiRwCJsAHafFwvf+DSrITr0p+8HZbHYSrNwmQxFIgorD5tQujNOhlL0AVo0OEiS7d5tN0QXjKsw9wqDwKouuOFT8jNHRiefFgWR+nuX5rH3x9HQabagLg+HnNCOvl1rvpP7Oe7oLtSObopfVsyQasHg+bg+UmJoJob2sLSzBQd7u7eC0lYbXEhyWzreSTqSttcUrtP8fB5Yu8jx4QdI8p2jMy6VTYLhYK3/2PP84JjdAkxzP0sgDaw79WQTtksIQZvtKBV3xtbFQiHL4lz9UO3jcJ42wAqVKTh1OHMb1YMz6WHkMrsW0wfCNEPxNpNcl3FvjVKpDtwkc6dfhZhzAfbLBqbgK5ypJJUi49YovzLCjjTv2dy9SRztlZd+JqHuOpyjgaXJZbUz0+oJkUe1G9Ne+S4lZUR/gGsWsXK7NhpVoN9C7pxuU7l0W55wwvVo1IsKjsmfpcV+Xp1lc8NGb0DRpUVOhQ2ss16DjyDazdZORbAd+zKFRcyFjXPIeiBScB3Y1oaVfYMhbEgJkqDtcIeMWxzEZp9Uz1a3zYRSXZaNyPHj0VYjEASR0UJ621pAGV5VtTXZS2+MtwbLMcHMgdSvtQtWc4idVB3XPQhZNBpJwyVEj9TFnKL28bsiKOo9Gka3up95sZbOZlXnDGN0zuMiMDXv4Dvp8or5wGxhpyOt58SFt/iFWF/KmJCS4tKMbUq+S7nIMjUKEpGxhO/0iWiq8mw9gRP96k6/e+vAV/ZfDGhSiMYojMjmaHoCa/Wt9AnigN/R6/4tjN3OTHGcUWmauMUQkRj1NccJsJ6DElE8+rbnZQ97DWXlnzRxVxWkmx0WGVIOoRkc3ZSu6gkK5V4lWARlBnnADdd9Axu09PZGw7OsPeDI1TWhc3Da51LsRatNbRda61c/ncOAUFpAio3mHX5IPWCIJGwy0E6fb0nHNQ07gpP6C/NUfS4efxt1z2Wr5JG0QFszbKpmFZRyvNhush65Adnf501A41B2NVxKoVpCq7KsgmujDk90zIsNDXel0z8vipZPk+g28O2JNSZpzjlg4DlXf6U6DpdvAmFhEllKIYa6KyYjUinuEdW/O48dzSuhtn4BFFAtK+8JSJmPfwC8IC0lXUBCu5K4phttBGs/cQV69Kn1Gxy6idyUDTApGFgibo0iWC6OITMSFW5b+Vc+VxGbGtCuHaj1kK4iXi9gTOV8UHssT5ZzPeBqubCiFwstIBEr5ZLlPmxxyMKBevPJNwqHmaR/FAQ2/fDBerXjpAC7WifgBn3e10YS+DJD8zd1GRx/8cz0NV9vi3ru7Jri6Q7zk4yJscjNQtEytzXX9S8rSJAJj+xke348sMXAmzuFdpO7v3+OP+Zp/HTY1sy9BOKjKnIys4lmLlMomaWqKZ1m8rrpfo6gFEx/v/ofQHSvyLI1E2lyYi8GdNXajI7HuxQSmnPYFtN7LPw8H/e6wbduMwzdbKxJ/Er5h3XNWikCIY7b3zo3OTSrBDynSvKs/RXccZouWy39G2TcKpMb8AQyt/5jC5HLzLTy24yGtXSr6RF+Kr3W+gWOvN4Xhfo6rMeHEAv+bJUzju1Fgdv2t7k1NWasn+yohJxKUIlDgvnfMgsP6mgaeT5cfxXMRVGNV92u3cfAfvXOZHt+E3MPtCuEuPxwUZUkQmTu2V1p9RVk7gk35l+WM+Nj5WreYmEHPqIgtyB10i0S9r7ttcpenvZJ84Z/mPr+7qUKPXg8sLeK5H4WpMbmbFXNeayrOVERqX2mpU8IhIMSsmrcp52+3Vs2VHx1qLD6Z7JZ9bYkGJ2ZpSZyXZ18HgzJBIAh2fmHvLb6TDzcckKKymqGyM5bIuf+D1ieNcrW0qQJ/fEYP0owLfQBy4Ngt8R0pHoT2YhQ+aOIdXbbTwp4Yw72X4inYvAKokevAVyFK3bK8gTvI6CAfxRDIhpZNdIAix+YrS7CJCfL6Bj8H11zkiupLHGXjfg9Wfra2uDh5n8UTFUZ+Ms+VPoUXi+35EsLhjmC6NNn8qZKIhJiU2OIOzUNXC6BK0D4yKMt8rqD8Dm/J5+YR2XFlZXnIhdOnzk8Sm4mxY2IFDuxZIBajg1v2yhrvBYwiMO+EjiIxsu2lDr8N/qCGHa2hplMFXtH409IEaoIWeo+IvtkBP/iWLCinIaRSEZ9sYT5kEjvbjiUb6i2bjO3sDN4x9l3Zr7s+UhAHjGgI+GAOJlKQFm2P6MtD8d12PbGRxYpjxg6vu7fMhRJ1NsCc7T9Erl5ZMnE/ECCA4hBmZE0O98iJJuQtV6v3+Hf80v79e7CgB/l8BqzKXbMuFVg4fl9QpeKcYKCAHNlFYkQ0z/Ec9hUak0TAIE08SJW7AmECvDvG5p3nJ9+F0UcWcYTaNGNZFdhPYvn1ye5BRUvt5309zPfGWYIv+ysZrkRN/BNEaKHjwAaoIi0kJpXgLvwEnyy0vGVRRxFoRwfC7WyS5wnAQK/caBUu1ZH4v8fjB2dC4WWBCddlaXOpVLChadDGkr29bMUYbVQRGNiugVXpQp7MZK4BGDKZPBD8rTfTh+AdUarSd8Jt3s4j9HkH2tZ/BbAcu8l/M8V3l5h3xRYuCW8aW6shAig4Hk4hpF/Eht1x8kfaqIWVkk6ib9IWgxRmMg6OMM2NwxmURfuC8L+fye6jdeAxe3IC/cLKA/dp2QQQ4cCtV3o78ymk8koFyw79EuuOZP0/tDh0gXts8zWdzAL2qahAQ2eE2lNpI7uWZZ5w2YGk154IU5XbEmL7k2muE0I5Ad1wsqLKJLVjg/EPbf6rPkrgJYS3ieVojTF3ZmLvNleiKoleWVdPb9rfx7HhByl88pSZaGHogbRXzjKYjVb+Ayw35UVmnpq6V317xpnG05PfY6T4jU2nvG+K0nElMxVg+7yUzQCsDZxU6YtE1yz7Et8Zg3Zbj0jXzQDhOmLQNyLF4hc45cKS51yASWDPnNZ2KlIrTacqxjqWmk7Rs3fHnTqqombjK8obcm+K8ZIdJGpHltZQz0fMawAawT283Ifsqzz2ou5u75N5MHd1TFURv/6cv7qDbypnawjIPX9B2nPNu4nztiHowXKFJUY2IkqjEbtVl0zcEX0hsm8HkLoLYY5nUt+Z91cNOuyEQ+D1vQabSLu/aJfDRK+2GuU23/8oJgRknaUpS3H2LCQCKZqfdeZjlKJ7NPu6sJoSihWtf9heWk2C5nC8ZrL74/OmrJDUQ/6DYrbSUmmMV/h25chAffgqBDx/v9I8m19y0XOm5Kx27tBHUqqav7Md/fZDqWOwGBMYDdPPA23aIjmF9MfEJQIcRnSxBHPlGMZ6s5AbNBcKuqjBXNTvj/fwy83yRkU1/7hkY/BJHMPkKjJwxrpUkQQ6+RCr695FFATiPWoemxjhC2XpYWf9zZdTZlTedurASrghIQhUe5bkx7uYuiYMNO/BwF86LEVOC+ZsKqjV3ClPMgDLGxpUHI+h42hQH+ydMB8xHQyo0lmBaOWhYcQ77k3+BgOTX/68nWclQRrtWYCa71Wa6G5iZLrov/+OMXDQn9Y1DUAl5fn76aC+1BxyEiAWmazmi2CIGiY8Db4o94BgK6BqvcnYAPD32VXeVP1pANQO4Swr9/YBcIjXpltTLfUopVW8JvAW1IuHCtF8DKIZgc+vfqzibNz0T8qavB4jIoLwHDqoz12k2zMFuh4VhMg/ojToImJA83LvwGBn/rnThibymrARBeEpVrivMObINFkK/pAn4jzV0+KMDEUwJ5ljL0vuLqSfEtUBJPkZhUIFkfPM/rIGa/hrn7QZlN4nms2f3/iWom/hPzPC/g4z+RH7on8Tb7PLnXMEGyayrG5TKPKz26mEcTvRADmXeB4yASDrENnbBZo0s2pWkCT5QA6leIFS/Niz1O6R5QuTpUPQuvoiW4PDUTG1f4tzTCljUM6sacjuNkoqUWWZxy7U4GFvVthWBGcPbMGbM1tyrlnhUi+8suato+VvXxoQJN+3wb18cZn+hm+vVdocJ0zae0ZEiXGjcnd/sW3XwR7IV8rX79AsFxAYkKqBDcTW2GG9b9jpKcgpAJmgfb36CrKyf18QaO8TVGSNT/YKX0XMZgLFc85yR1Tnvolcg0Z5xFmdridrB6gU5nIBxQ+EPnWJJkFDftJpBx4YbmsVHjAZxecLa9YrffOjDbNZganTW/wylmR8Q8wp/OoCo7nA5ItHsZjkzfLjlxOjPhwvvQxwRK2xaCYw67DXoU1WL5JritPM8quCeRz8/3N7/m6r7Z8YasV4Nl76ku+8cAJv37FoN1FfkDELKTylDjsfUqgjCYcZq3KoE15l/CDzinmMxShDfMzdkqPCeeMG6AQfCq/wTz0fkVnvkNc1x7QYTjMvxShYq1zKNzNOfsbVqOmMLcmVgplo1gbA0qbmXbjZD+FbfpbjE+FwPbsxKb39qT2RD59y07Uo6uBtttuRAENlfMYCibK/TFewNj5CgJWgAq4pk3kDRHWtGYiwKrzxY7yf5CiUI0wqelSFjGnSfiQ2lyqvmO1LMWg1WKXfnubJqNzVLTN8EpcdiSdcM4of9ZHTcrl8yTlChYUCgr3o6L21QQovftVpAtx/MCx79RwdPePtUyXoYQJ4BAjf00vjCaCIZIYBKom+0sLIm/NTK81m9TF0MndEQquJnRPWRFj6w4DwJJCpuGn+IE24gcnt0Rcx1bHoZ1vEGQCwru9JKaqBMaQLkU9QlApS7kuiXaFEldy289QOcrZ1FQYy/bA2CP20POxi9EeqV4vsMIwIEkctPwgTOg57qUCObs7aEq0Suk/4RB8JAPCftq2kJ6EJlb/bOORTteRqubFhY6OUgY8fV+69CYm9UN2SkQt+nReah9/nr7MEwnBnoZlXd5mlPO8lMZJv0VzuV0gahazEUmbbuYNp8cste4CkFIn3zPowSCJ6KfbTdCGOF8TglQ5cEbBD0pZSvoAbTk9XqLOuhGg+39uwbqLT9KamwMD1Siiy/oQMrvdi3xwq0Sm7XVYEttfMNkB3KzSSj7Jq7k1lLBTRnPArYeks3cQjm2ysa1IUuDF8AUQ9fcVxYUKn0ZZJI6jAcUw13IDs55D6ecXiupczd4gAVhpTUTY/bZMzqdiHeo0D5Gq2hSNAh8ofYmMHdpC82orVP8vLEO7G3gCnG7stylzmMCjzs5VTvm6u5/h3lOYR85xr3aXZv2rR1xhHSgr255ZODRJiMRrJSchgPPg2NF0MFe6xySQjhSFNSbvb4q3zAuuUAWR/zSQEGpzjLuPpFg8uCTKGE7UuGM2mZxn8AqjvTed1gx4WEBBGAh4u+IsLMEPkWu6TIwTFHqtVDZn2ntm5tIekR21mBjr6qXMGy6s7TqERabf1XncOG34Sr0GvPUHFOk0k/ZaOE/aV/wTW6JI4A3HawGJmpaZH+fapwQePakJh0F7qP/MmpPphuA/FmBWU8PjZJfR7nJb7K6aFaDBXkX0EpC5vWk=","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"f7f0a8c0816ff28c386277798cce9f4aa92e1b36","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file diff --git a/09-IMPLEMENTATION.md b/09-IMPLEMENTATION.md index 96c8106..cc64660 100644 --- a/09-IMPLEMENTATION.md +++ b/09-IMPLEMENTATION.md @@ -2,7 +2,7 @@ ## Runtime boundaries -- Paymenter 1.5.6, Filament 5, Livewire 4. +- Paymenter 1.5.7, Filament 5, Livewire 4. - Paymenter core owns pricing, cart/order/service persistence, and the built-in Pterodactyl provisioner. - Dynamic Pterodactyl owns capacity reads, node selection, reservation identity, and lifecycle validation. - Pterodactyl Panel and Wings 1.12.3+ own actual server state after a verified @@ -34,13 +34,13 @@ The extension branch must include: - exact allocation claims and fixed-node upgrade deltas; - legacy readiness and forward-only migration gates. -Deploy the Paymenter 1.5.6 baseline and extension migrations together. Migrating the extension without the companion core leaves no caller for service binding/provisioning consumption. +Deploy the Paymenter 1.5.7 baseline and extension migrations together. Migrating the extension without the companion core leaves no caller for service binding/provisioning consumption. ## Verification matrix | Area | Required proof | |---|---| -| Upgrade | Paymenter reports 1.5.6 dependency versions | +| Upgrade | Paymenter reports 1.5.7 dependency versions | | Cart | reservation failure rolls back create and edit | | Identity | resource, plan, location, quantity, currency, or price change changes fingerprint | | Guest | cart owner and pending holds transfer atomically | diff --git a/AGENTS.md b/AGENTS.md index d70e7c4..411f571 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,7 @@ DynamicPterodactyl/ ├── Listeners/ # transactional cart lifecycle adapters ├── Services/ # reservation, capacity, alert, setup, audit core ├── Models/ # 9 capacity, reservation, alert, and lifecycle models -├── database/migrations/ # 21 migrations, including durable lifecycle and encrypted-key upgrades +├── database/migrations/ # 22 migrations, including durable lifecycle and encrypted-key upgrades ├── resources/views/admin/ # 1:1 Blade views for standalone admin pages ├── routes/api.php # required from boot(); /api/dynamic-pterodactyl/* ├── tests/ # isolated harness; see tests/AGENTS.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aba229..fdfd547 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,7 @@ Milestone and release notes. For day-to-day progress, see PROGRESS.md. - PHP 8.3/8.4 cross-repository CI on SQLite, MariaDB 11, and MariaDB 12. ### Changed -- Rebased the companion implementation onto Paymenter 1.5.6, Filament 5, +- Rebased the companion implementation onto Paymenter 1.5.7, Filament 5, and Livewire 4. - Replaced customer reservation tokens and independent availability maxima with one server-owned cart hold and complete-vector quote contract. diff --git a/DECISIONS.md b/DECISIONS.md index 2eb9ff1..8c6a98e 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -208,7 +208,7 @@ These decisions supersede the earlier Filament 4, browser-reservation, invoice-c ### 12. Paymenter baseline -The companion fork targets Paymenter 1.5.6, Filament 5, and Livewire 4. The previous 1.4.7 baseline is release-blocking because it predates applicable security fixes. +The companion fork targets Paymenter 1.5.7, Filament 5, and Livewire 4. The previous 1.4.7 baseline is release-blocking because it predates applicable security fixes. ### 13. Reservation ownership diff --git a/README.md b/README.md index 58925d8..4040cb6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Dynamic Pterodactyl -Companion extension for Paymenter 1.5.6 that adds native RAM/CPU/disk +Companion extension for Paymenter 1.5.7 that adds native RAM/CPU/disk sliders, live complete-vector stock, exact port reservations, deterministic node selection, capacity-aware upgrades, and Filament 5 administration to the built-in Pterodactyl server extension. @@ -30,7 +30,7 @@ flowchart TD ## Safety properties -- Paymenter baseline is 1.5.6. +- Paymenter baseline is 1.5.7. - Cart create/edit and checkout fail closed for dynamic products. - Guest ownership transfers with the cart in one transaction. - The immutable fingerprint covers customer, cart, Paymenter server extension, hashed panel identity, product, plan, location, node, resources, quantity, currency, pricing version, and formula version. From cff5a8978d7972ec9513b32b2d7567593fb4f664 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 06:13:01 +1000 Subject: [PATCH 77/95] ci: pin collision-safe companion checkout --- .github/workflows/cross-repository-integration.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml index a2c7f54..2bbb29b 100644 --- a/.github/workflows/cross-repository-integration.yml +++ b/.github/workflows/cross-repository-integration.yml @@ -35,7 +35,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 15898c66ef4c67c03befddd898289a6879eddc29 + ref: e9707384a7ea8b012ec4e26f0a5e525b47eaa6cc path: paymenter - name: Set up PHP @@ -96,7 +96,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 15898c66ef4c67c03befddd898289a6879eddc29 + ref: e9707384a7ea8b012ec4e26f0a5e525b47eaa6cc path: paymenter - name: Set up PHP @@ -200,7 +200,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: 15898c66ef4c67c03befddd898289a6879eddc29 + ref: e9707384a7ea8b012ec4e26f0a5e525b47eaa6cc path: paymenter - name: Set up PHP From a3918a5f8ba5c2f19ec4dbe10070e374be621513 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 06:13:11 +1000 Subject: [PATCH 78/95] docs: repin final Qoder checkpoint --- .../en/content/API Reference/API Reference.md | 24 ++++++------- .../Architecture Overview.md | 34 +++++++++---------- .../en/content/Core Services/Core Services.md | 2 +- .qoder/repowiki/en/content/Deployment.md | 2 +- .qoder/repowiki/en/content/Event System.md | 2 +- .qoder/repowiki/en/content/Testing.md | 18 +++++----- .../repowiki/en/meta/repowiki-metadata.json | 2 +- 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index a080827..44e3723 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -23,12 +23,12 @@ There are no standalone customer availability, pricing, reservation-create, reservation-confirm, or reservation-extend endpoints. Customer quote failures are generic; upstream bodies and internal exception messages are never returned. -[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php) +[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php) **Referenced Files in This Document** -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php) - [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) - [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) - [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) @@ -82,10 +82,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -124,7 +124,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L17-L22) - [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) - [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) @@ -141,7 +141,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L17-L40) - [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) - [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) @@ -151,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L17-L40) ### Endpoints @@ -190,7 +190,7 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L17-L40) - [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing @@ -229,7 +229,7 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L17-L22) - [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) @@ -313,7 +313,7 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L24-L30) - [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) - [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) @@ -343,7 +343,7 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L32-L40) - [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) @@ -378,7 +378,7 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L32-L40) - [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index 6a269a9..d43d3ac 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,17 +2,17 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/DynamicPterodactyl.php) -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/routes/api.php) -- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Services/PterodactylInventoryService.php) -- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Services/ResourceCalculationService.php) -- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Services/ResourceQuoteService.php) -- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Services/ReservationService.php) -- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Services/UpgradeReservationService.php) -- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Services/WebhookEndpointPolicy.php) -- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Models/NodeCapacityPolicy.php) -- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Listeners/CartItemCreatedListener.php) -- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/Listeners/CartItemDeletedListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Services/UpgradeReservationService.php) +- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Services/WebhookEndpointPolicy.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Listeners/CartItemDeletedListener.php) ## Reconciled Architecture @@ -136,9 +136,9 @@ in Paymenter core. For implementation-level detail, use these versioned repository guides: -- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/02-SERVICES.md) -- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/03-API.md) -- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/04-EVENTS.md) -- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/09-IMPLEMENTATION.md) -- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/DECISIONS.md) -- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/PROGRESS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index d385cff..e5c5ac8 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -17,7 +17,7 @@ `SchedulerHealthService`, and the audit/configuration services provide the supporting policies and operator visibility. -[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/02-SERVICES.md) +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/02-SERVICES.md) diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index 67d87fc..1c76aca 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -27,7 +27,7 @@ by the cross-repository workflow. Before enabling dynamic stock: The API key and alert webhook migrations encrypt stored credentials. Customer errors remain generic; detailed upstream failures belong only in protected logs. -[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/09-IMPLEMENTATION.md) +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/09-IMPLEMENTATION.md) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index 8928c7f..600b95a 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -15,7 +15,7 @@ companion lifecycle. The reconciled extension does not register cleanup, reconciliation, capacity alerts, and scheduler-lag checks are registered from `DynamicPterodactyl::boot()`. -[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/04-EVENTS.md) +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/04-EVENTS.md) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 05ce2f1..5c05091 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -14,14 +14,14 @@ process-private named-memory database and rejects inherited generated URIs in child processes. MySQL/MariaDB tests may use only the explicitly named `paymenter_test` database while `APP_ENV=testing`. -[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php) and -[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/TestDatabaseGuard.php) +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/TestDatabaseGuard.php) **Referenced Files in This Document** - [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) -- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php) - [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) - [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) - [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) @@ -86,7 +86,7 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) - [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) @@ -97,7 +97,7 @@ U --> AC **Section sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) @@ -142,7 +142,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -361,7 +361,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) @@ -383,7 +383,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -425,7 +425,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/f7f0a8c0816ff28c386277798cce9f4aa92e1b36/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index db7f1db..97fc54e 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBVcsEy5TNHlP/Xz/D/ELaiZcLqVqvsFHZojMIvWXbqtAYqvdZNM8XlBghzpiqWnEov1SV7FQtFPIpj9j/EofU1iDJXVRmqaz5fZFYghM4g6eO9cJ4FK7JsL738Jk9Pp80MZLg8hV/wWALidFrhbh/4LOB+9n+7zkzR2sBNubQpQ8CJCXywcf+P2+Pve3bo4Q2XdnYCEud4sF87/Fh6XF/yl4YV+aVoUDW7tlISB4ZX7+yVhkBU+MHlkjh9Q3wsb82HFvz1GL4gR/pxDMVhhLV6eIIEJvhbXFJ9TfG5Rzkaobf7DkZX6CNWPqRb1vIa1SqQnWSD/KPpeGKRH+B/DFqBZ7eb/hSKBeb14MrTIKWuu4wRF7kOKMIJBVuMYWQrX6NG5oUKP1xUvJjDeerXVq7kG1AlJV1VqD5Da0c4KGBNIMelVdcLVBQOj8hqIM/vlr7KRkfTC1wKtE2Qz5glBCmIymh76+xzX8DCyNNMiLn+wCCGDuPzz3Fzqv8twRVUsvSfg/QLe0aWjgM4Rw+BePhdj3uGonWLcJ5ZvyKyAVlrM7gUoUMBz/KJiAlD4FAsmXPvIbxnPN0ApMDTVbThe14MgVc03fnMupeiO+tlEUSIpFtR5gIoV8ys/O3FZhtCRzI2DUqbXiqgrxSQ57B0nFSTKfuxl/yiBFRzI3+V03TtTUZ7P5Eg+v6wipDcAka3ri8fJWQU2mYgQkevu3K89lDHiaoMoTry8Vyn/wGR5dNvPy4s7hCsI5irNVhNWfZ9r6CqdoAxe2J4b2TbkeUQy7yb2RSbL5neccpDzlTBYIaTUZHvFwYl8dcbit+0GTXs7hFz4wiHKAWbNnjtTbGLFKLDzfBfrjA7TpLB03o+elWdqBN7rPnNy10tZf4EPIa6do65PecZ2hTDlydEJbb4nDOaklaESrjqhGkf165rK7eIbSKEyYHHbPycQhlkSvUdC3MamKUVQutZG46YTPy1ncD3CXhlIbO/VC2L/IZNrJD5WsqK0SaZII5Npo1R2/GM7P9k2hX00M+bo31khxj7QI/QC5uibD2Jx6ziB2BRGTNOYPQudB1IAZk4uvsQ+giuDZ/o4FZvQNqislT7Z4Ow2ji9qRk+lDNq65aguCByiNEEpUpA45EA8ZZypAR2Hkt+UaOq1FhzTcKEFSUbz/oyp8G7IUi1+5cMFfYyYtReYki+9ACci5DyyMrZKqznID2Gyl353hmIAIhcc17jW/QmIIHxFJ10eqs4yjyuISQCDq8b0Vho0FfatTBaV4nsWlecER3pH31ovCsTEBsIGFhDE4s2YD3WIstIMlL80k62Lz77x5HB3xkAkb05Nvq7E0NY+EiJ0KUJqUAST0bIQWxdLUL+Rg9NgCGbUPsl9J3khXYJ+5BcAHRQ2Qn5MJog60AwSaxXT5JM+b7EFXUbPLJBqbsPktU+UevN9OnstD1z6xZ6X4cWXQrV6D4TWM0sUtU8y8QaivnVp4s4iYwLfrA+cEHtwgJ+5PrHPD5FSjswMY2Z7bu7Tgu5Txo1oKSABpv9in19t+HrwN96Ik1yNFe85QpLLF4F+Y5zQZU9ZDYtCg6illkCxGGOBCF0v5SMF69/tkU5KUaEVk90va5y5tKsysiU92Ds3eJkOLf39k8sUJtH0yFu18Jbaw2GDFpO/d/VkB797dJLrLKZOeYFeATUISpwfU06aFMubaqXyblgKy3+S9ki/fVVX5z6ThiXVs35OPUAKrq6ChluTdaPEbFFo0zbPYDpxEsd40/pybI/tgV7fFfXHwW4LUfcIZzS7HZkTqfcpBBLT/5t+cZ+LwSbtzrwc12elLAT4nvgcay1JkLDXREXYcalhltzpxhCrpaPu8qks7zzyy7bTfKGzzzEqAIh9wfb+3ONdQe8aCOFyB6uWxX8OLuuGWsa/vajo4XG7EeUA+z7dLlfPJFmsxkhpMHYScbbjT/SSkhlwZlXowmqqN/3AtHQ+m8TLOJKbdXj3Z+wHVKQQtV3hKuD/X8OW/D4TdgpS0/n9o8Nj8BP3b0qkM","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"f7f0a8c0816ff28c386277798cce9f4aa92e1b36","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBW0kY68nN6yH347gACSKnGW/GaWsrfe1qmD5Vs4yiF9Bg4+cNg243x5/lrCPGe0ZLa727Kgt90Uf0qPTmGz2CCcagpDlxGuQ7KqPUQcnjLaS5faJVmqkBWfw6JX8uB8qtdCgeBozoNT8CS3Bl+VaFcrfo46PhuL+4MV4UlG69rB+KEYv2FlCDFDg9dsS+3XTkwBCvSqfvBNpmup+JH+w/q41CDiYfTbbURVO8q98JASJEHxb7rNSya1EFRu03Dndw5/hcunp6sW3i/mUBf3rxpXMRj7LhAAzagrVZYsK5LpuTLXislaMmRF+QNJZ+IT2lA/DQouhtUWc62leDrTc90zHDuF0e3jmfC8eu07DCVNzcVaikeY2HvQANYSq9rcpC9dzQDVFpKkVZPyhummuPO6U99ZLXQfwklIsKdCVTSZVinDVknwHBRxCYkuHbrR8PCWVfl3nrZOl4z3lC/mgPD7igYiJ64AUnOrpRNW3FBxgRf+8BvCrHeO/WIMVcJAbwWpx1XZdbGR+ktnHoWF73udn49QqG7nwtZCHkmejnF7RE14lQ8+LnaecPtPbDVehaKMSZUoX61sD47oraIoF5YU4E4zx2W6+7KWhB+NpL6ko1IG+UcHaD4hkEfJeD/2SeBD7vRpayej1ACgV5vne+TGzI7kZjsnKCjMqmxL4YD2RzBYMKD6LQL6+ubIXcmtFJAr/Qf1KdnxmlKveyXnZvX/ndj/g4n7iBoa+G06u5nlxnDftLOS1UX5Akt9Sa4ReIpPgc+Iu4fZiEvIogShhlx03pJAKPKeqY42rc4Hmh/zj2ffRkETYofbIvn6wCSpMGtQgaNCIsoTBzZqBh0tM7Ms2F9sOuNc6VOVytLWrAGs3Uj9mAw1cTz5V3dDkS8Iqc+2KwYHX1PPfXqBnFJ9XWfpzrzj1AUpLdt2Z96y1BKsDO8FeK7GHaIwMaAh0x3oc2MEQ48zBkemSFRqIbRb6rRjJaXwqbblx57l65FhBcMxFJxsPldnLySuNmXFfz1BkfSZ5DNpDxfbRaWAgJ5iptfMKdXbJy30ubNAJBkJhH4W4vLOQclfbDxGrO05ifqQbqraigV+gsHDqbEOiWWDQntcPu4du6DA+lClzPznkDuMn7ja/xjWhR8ohc2fY4GLWlOImAZLQEAyJmjJuZjDb+wqcLkwv/j9SeZbOJGELa6Y6Cr8itehW5lwWc5TsSfqavSxmD9CM2kCWNa9KxKdXaIxsUdn3AszUAdFlaPjG1P92QEIZMq5VR63US8SMFRS/lg2Bu/R10wr78W2ugpCg5hl4fZ5p/1vmKfSOK9ausuHQkeqqTABqn+iCT1Z7fU7QiEJ1KksgoDFkz8d4juqNhT7IjgBmnKpjlFLoMF070nLjTwO0MpA2l6ecAQhNFxkCTTgbwRAIdm91gS5JWtJnfYT+O23P17YXLCRKgLW9r5xM89j/ujErpG3/BIYXQkGGTGjTpO/lzd6VuHMlCDRwq73TZwT6AUgKKmb39ODafcEgXDC0Bwj49ZcUbc5EUw20RKYOccxNuKtBfilv6f7hbd8Hu0elrwUXFysMGHrQEIp5zXnFc3NBoJTtz5sGtxvwxy8KxeukwOhTloRknS/PinVWgDSl7tIsvU41/UPsEcjYzvczZ7nHfW+gpamwJoBNcYBOgGuCXoh+r/X+5NP4J0E8n/b2wCID44OPvacVG4V0qgjxQD4xvuliHGhoyte4iUvy5yOLrxbtwVmw5WBJUPAVwPgvGGRdqqVGnUW9k5T6rUGgAYhhHc5FTr9y4OibhX47uWd5eEv8IHnOhQT5/OyBAM1DOPcI1CQf0W6Pe/UObhm1662/8HXjlFAWsAJiyHi+I4iqPHBoOO9+l5Ng9s7uFUXtS6a2de/JIymAUP30+H8rrNsAGFKDIDiIVgJoPtOqSM+8eDo5CQvS/Wtf9VNIbJ0jbt8M9D79XxKedIjsFMGtgC4JPtycHOsQu3VsEvlFdhN60jr0Dd8w2Fa1hkc=","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted:6mjqr/IowaZHmZRFDheV40UGsQ0sVJEEfQuKG2umzvjguvQXGNDi1nl747nCkFgOsOds5jYVCKsejZB5Ycp55oXbpBTWUOFuTcbJi+3ZrQm9i4kbql3UWJNNseqDdzVBXYHp7WTzFhQ0U5rqZB4uDZ61rmVX/LpmmgFuevs1x8owCRFo3w/YQxC110zOuoxFXRy2D7RBc6ZTQZk/Reik/DkkqHuXW1aYatf+BkXbpHcpfYrOqk8p9/VEp0mMj0gECCQO0Pqw4Hd/Sv3nADV41c6kckej0v9kJtXhZqOzBdsFT7mLWuylMl+qvHsaHJ0MDt5MzrpvlfrgBeGBF5Midf8ReNZ6ORrydHNfFH09xJE6cpbKTERWFXgTyuay7GSWk5DakToppKb1wHNu0axV5Iq6vDU/uFLj1Nshh92Rdd/Nu1PY5z+2DpuP/55wMgC5+trljToArBiPQOHJAn4PtzRb7TLb+cSeKIxDddZ0ZmkGII9iJGE5gsK+DqnvDEAnbNBlGwbz5SIC+7PUjI6rja91bfQSJVQleSXZt86XHg5MtKJ9EwDGiHfHOD5jfZKwxPWwV/qECGdRIM78OQo5SUuP6twlgFU/UnnGz7dRSHYYeoR5mdmHDNZS+3bThmZbxUgjSht5CiCg+6eaiMcph3vjsDgefJtfFegbIm50KOBcyFp/oS2o3GYLVYHq4Hs2iT2VB/R0b6N36KLn2i6o3cfqgzKAI6QQ1C7jRX+8iREvlX3lBr//FC1VuUjr4iORHHlHGiAYFO50FtKAbrzk9gdnSj/zENTdsp6cR32Pbikqe7VjE7lio3O6NQcNHlypZIcUM+6Kyk+NUxn+LDngSqWYvrLat+AA5GqBFxhmhMrSFE0N3KLrPKC+NdWo99CaBzTZ2A+bbwas+ZajkwtAP4yAR+r8xFyf8kqQJ2tzMX3Hu3fs/ZY5IL1SLOpUeolvQV1APALj4BbcSDmNdJ9+mzDyRnbHeUgoxP7vYaqUQhqO7QQK3q26sySlLGLC/HkuR8NMYBsWaAxDopofmdR1ATxpAKWQyqQW0bGBQOPISzTIroTNSM4RPKIH/wyC2e/stnHcI2UnMoRO741LRUdkDYjkoZ4pX71D5l0fIekJjyJVA9Y7yTKy0s6zBxOnGFh/5As6sWSqEt/KBUXi+w2JtZAsIgHRsuH9UkmJD4i/83YgEIkuaxKNDyiSJc18vS9qZfLAR3k6dIDnCeqx2EUM57Hw2X3lHksgjYxhueVcr9sltsnMjqSvWjTJcGusE+pg+8z8MDo4GUxQt9ZGaUS4ZvT+aMTcjHJXKoT7xs0XgHJMGzLEiKvjeO3Xw0Iys459ym3Ju0jEogWDGsNP+5GSkpYhtX7kVR+zPlQuTlNYPIW9kewpAq+PoPYmy4i2WKlJ01CF7HVyHK73SJ3cASCVTlxVlPoO8faKhwLDgEEmWBNQKMfE4WudF8NSSYf3+qVwzpVlXjK5Ws64YYGZb87dbP7Vc4Mr9KSdsFKOouyOkHfWjwGNOSjiMC/pL5mjRILIh7Lo+fccxeFT4m1nTHIQ5YGG8M5Zs3NJr2dlmf8BEc0G4q9qr9M+lzefp+gykp4fS4zsnw/DGl38T/eqr9Tq+saf9MLlHZE/KI/+soLxPv1McH9P3SeGZCVlvxlGSFoO1Beqn1guVZWP0T5Vvs0GDZhcb7HqkmxidrJAMfVnTde6+UT5awe/iqtB8M95DigmGKah/I9I4gqTYGRnHLI4C9AQR3yxlke54c1/hifk7Xj5XKrUXEKBxfyF3P3TY7GUMmtndNA9a06sonBYWM2kytc0U4e0AvSuPhJeEWoR7QGZqo0c9bdkhlRsV65XFj640N9n12eEBa4G96+SXbKVqj+zKeECjLiyMCKx3wDLHa9Cs0VK3KIcl3heMF6lMIzAZOKESrs1ltPN6CT3AV6bSp3F2jT/46EQw9KJYDDUJKdunvmZdpah00g56m20GiY4Jg/7g6Ka46DENUcU62j4muR/DrcMxA1hEfrzTjcGp+f2pze2z9WX5Mv7gC5W90ozOfEvK1HTP6Tc0JqLRj2U2DN5Q+PRfNMoiI2JhfhQm9Chbqmoc86RL3z1A7N88M6VPqamzyPLwzMBXt40Dh9qsi1tNVwA/s9TP1Q7fT3IOCOoclDAbadPOKQMQLHAwas2/1sFNyfDGBSuahQ0LtNbs5oNRHBkhLr+2DFiaeU8SSo9hDAKRzxUiCOiHNFt2XRd4c7zs46e9mJCd+pGIIDEDKKTDfD+Mi5vpVMSivc0q3OW8GuKSYqbVKEG+Gz9HxnmcGOrDcJkRrCulqicsKScSX5/6bWoCabWYIGTsC3KZSueEu7f7xbsyeocxHcOCtU7L5evb6lwfNaaboCWcTVtQK//aet0C70B28WMA9Wly02VeyiGD/RGYWCM7Cqhw9cn63O9UPBKpaoCza2BErOXWtOd9BYJrCahN1jzCfWhDWWquHd+SixiIg/ApExEl7LhfWDhH/yc1kc8K7hq9OlD7gzfJICamZcYrkjZRBx7LebsiA/vdOcyNxDVW7TZ8H9IaAhsuynHN+8hOIBpem1R6ASKkuJLZVzPtPr6nWvHE3Xekh2VLXKhZNd2vN630Zn1KLTKx3mieZk+Ojpa0oXplkte1QA8UDEBLVAXkhbuF9011k2Bd49V0BvMoFT4TDLVJtZ5vQODFyo0C6P3yUpxBKiIYN+DjDuGENy3jZcIQYXIodgg5b0jgVGTMS5uWJSRewUjx/UgZNmbCq6LibeowRk2JiqL4DmiKay2mkQa6BlLFyhjYwWTHddGNj3NrON+35+AN4dpdCkkCr2/kMPv5mnzgi3QJIqWUJXUHdUg3ZbQmG/yf58hLn3J1bLayAu4pSI5cMd7iDOcPx5j5+QzQSAVo5X3Oa1xmq6jiDh6/AAASkH16Hv0sASVxuE8TRWQFm88YShX/aUQcTgte0tD1b0EpuAAceN496lJMmSVM5izotMtraTUMIND3ytV+Q+nXF7PiN7N5HUD6At5Xg32nwCbQ4vF3nhQjOt5820Pem4fG82RyiZw9U3SA+uxVhaXcdV+WCG6wUh/15yTOBbdvgKt9pSm5uYioEumFQOHq76xkVgDmqmFo+4u5k+LUq/PUjYSFBiJ53/t+xu7lz3ZC4pCsqVO0cFPHust3mBOod8pBAh01dCPkD3oYfwnWBPf+MbnhO79AzA6UsP9Bfi0KOv/yLrgVXRaVMZGw2C62K+4pLxQkV0oaX4D07sVGZWTtlGn/BOFvX/MyM+17PAYd4OaEvl5gk25vy5cdm0PbYUX3DZFob/92IDZe6wXDqzc0rAIXRjCOLcabHIKGvMG3BV188kWylEKAzIJpvHKecNawEBwR2xNjR+fMAZ40sNzLD0vMxQhWgC+pQT4EiC7GgCmQBssy18L3QxWYnhjfws4CmhpeLRMk3PwCLNGw+p4xpa3v+G+mLeNlv0FABA4mYmEeOYhqSCfB+jFw4Chi5+72zUGzapammzIh/0GwNYA+WaA+q4z6atxIjj1r17hOM+jO7RGdcJjHxLcFMujfG3Vw0qpmqLO7CCVTvKxkDgMo7lTLTDhRB2nn6bYw27Sg4/SMcy00PIQ9UyIGzhoJIFDTGp+GnFCVqjbknucTfn88utRVQrKT3iOdSHV6G2r0i4byvp1nOtfK06l2mzCE4kVP5Nm2KuYSotlAGrKZPezokOOmWQSJhguOKILjeAYu6lf4MttjIF5ySTVpJ5CsWXs+bZY3pKN2KS3xY2hZtXmxM41S0cfnQJXH0ydWGsbBNLIwVhaha/boR9zi1owv6qWynnFkuASutH+VJtgoqYtge42bGIm8IiVlmfB3Z2q7kNchPgFPm7kfIALte/FLswFb6GL8hLW9O4pEG10vRWPrMkxu/5Cm0dM92QSW1njxOEYj0jHEwr37ZBVJKE2P5om2/9rjYU6CZg4MTD1ybE/t7Gquwnb9x8wm3NdsR3fhVPKOlJBh/XA7PYCDy20HtVSmvStbm0pho/HUmEVfyGQIrgbMTb6IAhumAKWb7NVkMkMhQZjbmXa0Wf0cAyZCwBLBY7AnwFuQ9niRrsjpQAeqGZWtyK2OE31WezwkpoR/X7U7IvsmnR1FvIGZAkKLIph00z7YguWain7pmC675sboI6TmC6XiI8mizzm6xi4F9tXE24+8LAF5Ff7Om4mSZgtyFVbDyTUKKIqXB8UftRmbUbf7sUnl73HsMrl1R+AB9rqOKvgQax9ip3OXwVGFcoPRMwqRlFLoFJ5TkW3FqTCrdC5mVDMAAXNvxHJiBL04K+0pyV5wZ9twfdJhZVR+OfNsUckWFf8MVuWsG7gtuzYCPSbUJjWiK6e2NtzdQTrWyOgpTUkoTqmrNofApyekFDaxJn0tjYeU3sPXMbvb9w+PA7j/l8qkplDfNiEnWRjljtOktshJHGeRYRIKpKcxWV+1iguw+czhG49VFPQRgK9xrtRjCsr5n7tAGJlO1VlJCEa2gOE6IW/Bco3YysRsVBI3dedsoFSVfs9DwTcTNIW4VqaT4MN5EtmVeA65cvfoHpiNQ6ef+ax2AVulUiXFFDmP7yDVMursb0FcXm7KIeDlFC8FRpMa91fp6nc14RrzF441OIyya4T5vbotuokwULzEP695MxWEBHhR64MIZjRScsp8oQKonpHbIec9spVDYiN1HaQW23HAq9bumrRlFiHH6nEKV3H9pXLfVsCtknfLhm9c8JyP4Dx0dFCxJB7Y3v1J6I0QOtj7wb6hrYcGl1+3cBPJyon0gk51eAspwzeHLHiuiEpuQnoNL+1fL3Z40orysvlX1cvpMol9bdmlE4XgbIXVf7KSJL3zI/FkUdoQUqLmYsVs/g5ZpQwrMz3aewxCAl5uOw6sPHhs2NYlYwrdwyGE+zUkDCyf3BssHA4/crZP47IQOnRufr7ZFa90o4IyCJ5wthw+T+c+h0VGeaNnhdRNp/TyQ5HNR4/qN9EdxO7tr1aJfF56hummn7yaTxsI5mIbmJi8uOKGTJU7RHiGIsWukchtx3HEwYBDfNbetAxcQo+1CLHmqs9tp7PF24BP6Qd7BS0nrdRz3nZJlb8cdJygLpDPj/4rh7HmB0e0EOg/2RUUUnRE0ZIZHRuJD2gXv0ZFEF3qIfgXW8XFjplaEnkihIdcnbhR9dl+ZlSB+bABD8w6q20smj/bBz1r4PaMsgnA4UIzHMLWV54yX07E11atWtmN9tiTovj1xuuqAwT3tNr0ZCcJz/2mi7DLYwAem/DKExh3hab4BtDKEWfkghoJZCJPwHQkuc1m6tABgoIs3hqQNfBKJDMINEMnpnvlD/C2ol3Mawo7EbdicIiGsc+poqrky3tLrEtZoOZ/zft6lb8pQM/mNvX6ij6oYH7lYvdtSASOmlkqtuSKyWRxlAASZVociul3HU1q9Xt68iDOvls+aFS+Op14OcvKzqpOTbW/6gZizQkohhXlujGKecvQ+V+WAnLEDgk0W2cA0Mlqt9A1A0HPHt/CND4J2LJm4AulxA+sfXYEmSv861YyYq9VaD0tq6p1LVpwQ3cm5HjWcv1idt8807Z1L2Id7ER/N7uOUS7L0k2UniL7P6QC4IEJW4JVHvQJaO/7Xc7DeUIkv1SiBiGVzrardAiMAI6hSafaWZwAvwsn5GfU5Ng9Uz6JoGf+I1rHgZwb6PP9YAkFUXlFFBqX6CQQt+9axTPKKd/AZ9w6IHHIRIXwjRnLupSoiV7JvgrpQNcQoY0LHxAF3lTlBd91gKvbwWAYTiv0QdBTgJTV9Uuc4Zdp9R9vNTtfs6OpInFvQc0bmKZXoTF9P6+iUetATQfRshlgx4BjtfK9khPcDSsCG9336Lptz40AUh4nmPzxXNZKI+nTfkGoGCIfqVvoUxwlgzFVyngSIll0RlNPMaejUabKI2uvLdBDmnVZLtvK6fW1OxjXHhhSdWwFjxv+favZ2y+suXte26AmFOIuyv2Rm6L9ir76htUVDmawHsczq4PJUZG4OtD8D4JKgGzX7Vg9n8EZGBGykh29VRFkV1oHR3DYTHuldeBQ3z/lyBRB8t39OWaqRQ7IrLD/0ZyLn1bB2ZvtTo6MvW6yLb/ckvkMvQXe9noPrpbHHnEHWnrrCtbVeWWOsMVBYjUgFKLJzeRxYUk+vibIKEz3a4/fTxll10kOIsOjIp+x/dchyU+lezTz0W2esT9pfc5mnIachMdOYDqlP31+OUrIYYX89P2cd/u+mDIPf4F5hR61WWUI4dKHEp+fRgRCOrUk84LW7kezK3W0B7ri1r25kF/2k7gwkEVBL21zmLXYXNFCMCBJCMc3iVDvKYCktLPUOyCheO63oRVbGCgL4LgDKP3gObuwT9xTUDZ+L/cjdbykPSbOBQdrCTWM81gq1n13ehk/T1jPoepjUGMToGvfbBfhAtXvDpgs1ly36iHB7ZxZCG/6n5PgFzjk4szJqH7QfHijwW9sJ3t388W/npXzXYu56ESyau3yVwRhKJ7xqT/E7woImUiwkRE4kwg4tk3eQp415DIsAgkSCyNqTooX9T2udnd+708V8Nwl/B4zXLGzOJQG8QrVfiuYEqRLReD057NhtQ/D/T2U7KGLAM8cWMC0JeVQgn+/tS0CcEhxWwBmVwIp7zLbkWqezjc35Z7mcRepBKS1Db1iTdM7YQdlkj+XP8me5+SHNzzCdfhpNvKMSsvFAFiIJeUU087OD/wEnMh3V6Ki8NXl5sYeVWm4qi09QNYPFgl0z/3eU4K0k3i9lOsGUuBSm6wP+0YTT2ppve5AmA6ioi+d1dbPZLnVAISA+LT8ObdTeW6T0wYbwM4bg/qQ6dOzsKfDpLmyfcYWmNS2FArFhua1s66ZIXGObc1IcvwdHU6gPWdFnkWGSTk7DwNJUyQXooUrNkYL+x8tx14/kOznj4nFBfaT9KQiiMNZVNbSb7I7HjynQG5I1rnPr52Q+yhJOXPMoEaRwDpe4pi0zTMNNEZMmcFWLa8KQi1A4wkCerMyvQhgf1WyJqOX9O36SaJZZxEdG13f3+PvtJNFvMn6iJKnJ1JuyadrAnOVwx/KaNbyNy0DuVmzeh0maLdTIy1yY3d1a77XlcNIZDAC6dAS4V3pVYogzBBRD6FP9kyMpQK22LJcijv2JCyS92gCJbAiR2wRCOYf1jImPbeDOFLCGK2DDLihrdSWMPXzx46qJ38IF0UuGxosv0tL7iZt4TrOXZQXtckkMCNZpLYgH65d4PXF9s4NRA00KmfLdh0z9ihpggvqjkXWQCMsef5c8jBivY/+e+xx1XY+7pf5zBbqi6+MmGvkRnhbmLhOcyJ/bqnVfXcLcrmMUoZtMk6m6yD6kLYau8zhrwR3ZdIQwQ7N3WfMbIo8hd2FekMVIDz4cVfzGtEkQSPIIjmJeUMZ2TsfM9jyzXkUMPKetiALE7UtWxfQ6eEYPOWLNjzbh0sGp+EUoB+6OvP/1RZzDvAncgz/nWjIAS8H2S4LrQTO34s5LGGZmDLRl9f/fVVrwfiWBAeiD0kBXSYTNeJW4wULnzSWlvYr3ll9lCaWdQOnS14yJFEW05VafnYQ3UM+tlbJlFozQ1zehZxNc2Pv3KF4yFp0r8o0fYtMkMnvA8Xh9dmvJ8A/tt7GImE7fvCZKxANwej9Raaf0eCwLZfdW3lS7FB+CZ9y48kXntYMU9JxFUnqoVQrF+hVMBjMRR0abCVXfOVAwbxvdAxIrY8qV+jVGa90WvhAkKkgh+Hf8yCiri6+ifiMfDnv+k1W0UAwQj0dLPop8z3y09Pn8A9G80BEPFmI91s9HJBsAPXccTYveHQktvoUk7Qq+W8b0dAsjsQFs8BcTvGwvQFCYvLo22JMgHL54hZvcvvC1M6sc8uDfzPiQAj6orQhe60GhvE+35362Atxb/fCtBAaKGebYAAMRFg+wsfAH4aEzHvhSFVl42JGPakQS7s2bTx0cbVnMLsBSSji47jIXqAXtiduTFP36loKpYOl7n3KmR7bLcewC7AeNctVIIQ+0JeM+5FjJEQ1EgYA/Ax7GmC+hdXezes3eKI1c6dMOjX6/3lF00DjU4+AvhBkrR3M3ZJAWqr9pSB9fy8vmQRanQxj0Eln4SKNu8IaZ4WbqlEEmbOFJ6u4Io0RSvKzklYMzlm38bNqqEckKRNGspPs7uqYvFfqG2HmzKtzJVJuKvj5zInVSXD98FHeTFA4Eg2qwYhb2H76Pqdb9GFOMODMHna5A7uU7jrSMKTK0goNnv7UZAPSYdWdAEE0E4kHh/F1Jo3J3tOfqXI4ELr9skT6zKbOl6YDbPFDMgUF0IhgO9zQhKrNTf78qxC1KK+lA8KRdFFQb+PWgT72S+ME8dufBZYKNvbhX/QlkgrDm2qmwIU50VKz8MCXCQnYEmjp6jiyqd1FmZyyMg9N0AXgHaPAQwzWAmB/G/YJOGjmk7g1+eu/m1GCOljgkooweAOnryPDQEBmgcG9T1ps5P6ps+Ya6uiU7TdbZYgAZVI6oxeFIPYeGtMqCiMkwDcmWEfYlp16lFc4lVrhpE3wMtXl8/h3UsrNcY4jHEnsWf5L7wV3ukaj722ZjoQOkGAFIRiMyY8F0CshW44gtLgWetKFAlJ9ISdV6GOFb91ONxkUbRHNoWthbRayDDBOixZIi/5w9LMwGSfxfCyzYlnGgBvxxZS/POsYb9WjAVOgYqj1+gA65EpkINO5PzzG35AF+ti3s4QqSQWtuW6ZW3Ry6uThtt/Tw0EDlFDUIXd5K/o3/U6EYl94tslMYDc+AIoEWRTkqTsbsm6ZlJwQ7ARR6pJNWX9/7NbE9VjDXFhhVJwnKWCg9dTi5ifCRMW9eH0ek0hg8fwYi8daC3JoJHxhyo1nWT1HdxY7Q+UxdvBh84hlvXvwD/pA8mD9/NYSVJ2n1O0PVGMC6oQuA2SFQ19/+z04TkDQEi1x4uI3PvE7w3kRn3kfev7JrSJ7508vfEPT3MylzWYGnNNjlstjJpkubu5BRDzKC+nZwylJhJUhrhGCH+SfNH25r59CTULN9buN3C9ZB7Ea+gsFvnZ1TeRDY5tzP5u4RzCkrUlC9uhhd/y2BXjMzZD1xwL3FCXMECHccdnKFfpjbUrhqVFJ3RubK1osuMzNHQ6WR7Dy11GLbvEXA0F84yos72fYJQxYgjUb7w97j50wmnnL8DXDXrQzFxX8Ahwa6PtHwRH8FyCcnvqmH92eCU6JUf92bp3O8J8WKGBO+pfvcFSCpvtZhRpvbMlaus5d3Or7b5YmFqk8ROVqDqFPIEhb6dyDQsdzrs/N+X0hwLCg9cDxpb5r7JOg24OBgqtQOPsOCK6rMj/b7dmPIbmaI2su0QMeNCO0wUpim2/7GiVNgmq3I2Jlwg6ZlhZyz03TiGygZc3nLzdH75C0zPglSVXojAWCJps2cIHUozW/0ivvt22v9+WwcHMnMUfj1GGWs69rtru7urW3Xz0bcX5sAkftMgsB05YdWZJhZkMiCldJMkGfvhUo61x2DRig0p9+WhKv0TUTqABK+WAbT4yjgJUS3dTGFpOGqmWZZRVD6xXEFCsRg0mSDubYcSU2YoPE4k0676dXLj7L75BGaAskadGF7n2eAxJ286S28xa9vm4yVZDYlTZae8eI+3pFTCbFevS5J0kGdZ0TSzy1NclOpOPt7vnT3LzBEYjxjILS6xFmg5+WXnGyAW8YDip0bSslLGkRd7SaolhkcCDz6r0s7gZjFtQbqdScI4odDP1JEweS7TSw+40K71Au698JTMvI8WnIcowhu2blG2b/kOQfGGlaUUNZoVnWNw1IofA8mCYAPSNwPhMsKyBPaKPvY5KAgCAIfHBnyJyXwOXRQs9Sdld6+LtQcuIBv/zeHlF6w3xZxlGbiC6G7Hb2Wo2TJfUJ4tACJnONM8BpETTzFtptGgNipolfvjb1+vNsWAByCkv60yOBlFQcAUzVu0ZZzSGNTSYEqgd5gYtqRNOjXpAIZTxw77wIkfH319Ud1LdZmh29ynRBprzEWjUOi66Q1dRoLIDK7pVsItHaDTmvv4ZnSQNhYqyifgnpqZLRzG84/vlPwipBkOlO4L+r1zpZvvqY92xyhoPnL+ODrrFvaKqI4aHdJBIQdMGJecD9t28ZLhkGuUG2QNpIp74uD8eJUu4qAB8FapCHd+kbaQnXlH6MzzinR7wrcgWB2ONA3E8vPjzmZhiaqi7ZFfm8M8AdVWOdxZYhzBWtK+/CiL/7AO9cOQx7tzl8BNb0hK51P6PZrfnitbvLw6FIRv9x5Wdr3eITxCLOm4hjKr+yKGSG+wilmAejJw5I+eFZSNQ5vYrITiICkpFodOC8V5F5EqeosnDvQIcSs5OeR2AC8bPxWjB6xi39ET96Txz7UUC/NxihI0SZBMmVd4S0ks/kb0RDR85/T2bnlGsRfaxa1LYBKkjGMgw0SwWAuqRoJltDK5RIFKEFdlh5tSmsA1Or8T+PDd59CfOee3S7N2twMQLZnTyZMafxdcmP67y4oPZezP7Bnt+wNqF134fyckNDfmXkBRucAW/OuhZS0NkA+3nOdCBq11LlDoTWgy1OW2ljr9/HbAv4VqJJ0YmqdOjBc3mEP7kOcB56VkzZG4TbgUBxSFn4YzDMDI26MAik4zLCiJHTUKonEQ9tvp62qqO1nXIt7zV3l/4cyzyhTQlcFkXV8PjKBYH4qTUz6Nbxao3h6J+WmfKTZ+IvYGl4VxKteJJTpPSv+QWNgqqgVavZW8XsHZzukUB5IRZ7/H4Df7ABQxoj0LzBzE/75ePugTJuzKFQaVHn43L+NVo0ccFQkC9kTiNg/vzAhRVtslEXSKwneKpm1pIeZWNdZhccTrQ9gLciXENj/W2H3GfvMv1vHIoeBKqaOSOgrx9ThjiQuKex3s1U/lBBC2ke1euyeRJ8M8K30fbY9I71fAAIYV6CDK+FZIWroAss2pHFYpkIfIyZCdc0LV5X9xUrLVHCLx842ip9FbyCj+jw8zr8AqG2Ad/1H1veTeRDo81gktDHY/1cLWgncmuueupisWDTjod7wbnFF73prWdsWJbBh2FyKAsupPUIi04tiV5Xi9LZynAf6Aejt6IP1vKpqkqg0mgIXPWx11JD3Ck39iPElppAzPlUklgCH5CtoacG7KTzrVJD60VLALKPCaJGXoX0vBl4z0sNzbx3JWrW2bZPLRez4J4EK15PpJ/5TmsuTQy28NivG9ljUB2KMQXO9WcDdvZ1/VqFaBb/OwhtDdHPkQAFOYe7uW/fgTeTFgHx/NCnzEMzx7B79UHiabsHDdBAxTNLophWX+5tUfY7qxLweL9hxSq4+hVt5/QUzKmhVvz4UD2Lx1FRAJS1EOdUrSmmso6Q7jklo0e7sGZEwKSxUEF2KCXXb0r8qTjUExpQqdONtE/aU28jpqehsHk7XRhPE2dYPS03q/Gm+T85nLBc2cyQ0TYYx2Ejj4GqXeNjXkWc3mZ192ZsOxyh3ucq/9d3JvR+SzMdS4HKPyju0YbeK+mX+NFm6bnrRakiOM9nZsEUs8c2SPX+70lMzaPBEWNpfFrBVPtWxqRSSpT6Jce4C7L5jJeGfT1+lCSooYRKNgsNeifaQDgPs1vb/Mu3xRMP1ZvqSKtFRYm50eguxyYzvg/VeWunsvTn7csVEAUQEfRj1dcLokLmWk0gYX4fN6ftixM255HXKIHjfx23S+lW1gGSz7SAVuR86ew7fmwDY6u1R2vqRBEM9g2Ualy96gx6GZbgQ2v5/y6/aGLCTAWSNwZaUHNihS0KggKyqQP6fK2PZbaCiiKmzWbhsGjOVoRM9j/VFlyHdgFYoGIoRjfU19PCjZhnCmm7Lk8XhReADCMZXrUvlvNbe0JCzGPGoYTn0HFVVCoXM/7LxASiRghqIjmF4OWqLVFTQ3sc1pBbRo5BsDcJFIKf7G4laq5a8EpMO6jKX0/rXx2RJKUIaRlHGUkSPX48tuOsFNrpgwozw/TE+xSl03ZU+vLHctHLwXEcojbuB9PAt4K+CSZu/zzbYsA86LUH9p+tc4Xzgn6bX8Ztl+iT1zmrGKh/RWDjZ2tJiLPEThKC+ihW+D2AXn/I0SLTFmddJhnc+TLBlPUJl1G4q+F62bhYZH3aJJx5YiOllGpu+/C9GsjN/D+b0pT6V20p0F6sb2bwhhxl9aV+yoL+O4zJIO9FQv+HI6nz3qXdSZt/lZVltoYmw/mCKmyA0Ka140Y1WH4gTTG7nU+Q1FM/gIxRy3ncptjOYZvQfLhYoFv7Avt6o5zzxHoti9VqMt9j410SHYVKQefZMCnY57FmI0yE0bt56TwrXs2IUUFQ83P9kmjP4/AAgjeC8chzIR6x08UjsUvv1z+PMD490ZDWEI6ThAWTAlJB0xMWzL49F25B6HTtdwj3EsByLbjiZnXwhB0wnoiC408/ho1QEpk2QkrtOkiAf3kKJqgHjRtv4UQ6WwhoqkAq7xLRlTKtvtfm87JM0xQJ3XT/72BaS0fdusbwFPXolosfpeHFLqtDMsWPYb7QVDJI6+wtB7DG4FSlRfqQXCH5IkKnlZxTgap2Qd1EFG9cHkivPVMNgdhaKX5Ek30p+65qzPwrQsRtpMjk1bjqL5sH5yZMIF10GJIgajMshf5qx6SlMAdjB5o3t9HK0oZCfBk10eEXXlCXhOCyMYjtQFl/dk7OwJU1oR3olm168FhFz0DPGiyuoLYZ5ZZYVJTh8YShowibINrW+uyztaFNCnVC2orjpOMEnEUeQw0JD7LkQwG5XLYBRXZugCSZm4Qftmpq4FBPgXGjqEmriNDK3chpxHADXSdYnW5NmEp82CvWti+YU1wCyGWA2MEHu7wE7lIiF6wLKBvIs479hJrOISPOQpl0p1SoE7rIOmGmVFMhBljW/l+/d0oTWVcGYkltEPHoScYsdDBgN+sHWnjkat1Z1yNkqOA/U7J3dPfL9vM8NSbiz7vCOnRgcNtjJitxkbYZGXy4WbbCwFFP30v6+fc9tPM99l5Nz2z4EfHwcQnUv91eNXox3LsnzaW3fSED/PhetXI3hkU0kWkPezG4ZkuIdriEuhuHiKjgDTmBQWXno9TDxkQj/aUql09QJa5N1UPmce53Y5uXqanGG4SGyQ9s+epdT5Vigc6Q1lC+i6ZeBTlij3vT4575jFkIqv8d/1X/XWoBEgtqrZP6eLSaYLo+r3Wr87hzRP39q05HUQ3fkt+00HmT9QC7h2rEMxR5ZWt1pGJSgcPZqcVgvsxPUTxtxqom+uv5Z6gODyOjG5CSlQY0ALfBz6JsPhAE/q+YTsCtTSMmz6Uy0R/Coyoeht4nqagfm/FoqfC7dG9qtc+FY3LTC2r3mjNHS6ar4QIynNPF1j9S1HQAqhJDBqcXRk0iH9XTlXq/0p8AkdDhQ35Eb421xJpgcVkTgBAl8fn7ZwDhc7zy4QXVXitL2x2wDhbbEfLvUKO0DsfA3pq/uCQJc+FiUGKWuVyItZHmSFmrPXHsO2xc/X5l35qbJIM+4iyfCizhRmufFsQwoA/kIyp4+nVNmtQXZ3J1P+NAaEFf6u046uNTxVxwVFEkaAkYPhGGI0aWnxId62Z3nJFDgwg+E9AlW1iWAvJewOIPwqSrfl59ZWxProiUO0htNns68hZCiDI466Phqw3p6GsAZ+8vHk+4EIHpmXm6QiqY+OrGHFB9d0YWBEGOvWfoBi2Ly0Hy2ftH4NoxTYJJx3TgmtgvG22xBaLAzd206yBcV2rfs72Q60U4LKl2nRojE5LnUXJNNDBfGp1RjaTmtPyGwMJk4WhMZilTf8mrjktyde404TJGSP2mtMchTyMdJFfZvqpMrfnfMsuQw1sYVfJPa9aij/dGVaxMqrGJxdPVxIeuYVMofV3hweFVrAZWJVdu5SrrRRbAAgF1mnAcrZ8qjOcftMA5VuCupRV81hZLIryA9Wmw9RcXumv9NR1LqGCQjc9l/OP+a5n85XkUxGY4YqdVQE5Fn9y7KHU3o5REsgBxf9spOWTo0BiX8Z7QjDNcKlIbFbJCGVwtRLZyIUpuGknCjh/fzQqpaJQT37pCFmmAtmULb0Nnj6bnGxLjs68r1y5UWadqmIRbB5HZ7oljRYo1bXKOMKRtgwYXS9LFEppyQzwbiR974QZWRqdIEs9wfx6nQLashFS6tG14v5s3FV/fTFmnczwwOq6sJb+4ZGYDJtYVPwSWtYJvEWaG3fGUz4GdeZPajnoULvy8QQnlCCqT8Bkmxsp8zpGwzoNbBGsw7NfU+1HvOm/KVkn/rVbeejpKvx+QfqzvtUsoi3atH3eowS+DZ5GcPfQfSSgREqv4GntJt4Kp3jd3Wjn7mTBYXF2sAJKTROvumsBiEkZu2EIsA38Fc3Ui2GwELKHoSAyp+0JY7rWJB1TQ3yxcOqKlkpZNIWQBfg7mgLfrmHeJ09fQMRomFjfHTXDQ/X6C3oyUwWiPeFNh6ePrS81SP5FzlomMahrmEbirk6yIggnI8TZZsXOvMvs2IdwFV0wFr86Vw1Z7az+dg9X6SAm29aCCK/JsBTN6NF8g3FekeUGYZFIQ/0Q6BMGhCKSFFBxW3AkhZE0Rj4IarQG7Wpnss/As/IPYOq6LyZVpAAKg9R1ihA5xN9Rxv62yoh6StTU3YoG40rvyVUm1jvmR6d8maXUMN8H2RwbA2zrVVhy0ZDqxIIi7zloZVE7TmjiSht2Fz+zVb2+5uUvoB3EnmzCIAtmYPDYtWBuRL8ymFbPX0GmEjNGEnokfOdKcUiI51QTmrLUnp0rf4r91ispSQjeRi15vBCff5qf2zZNVHjfjZQBidMAauaXpijbhdnj59faJnyrfWITXhGFcQiwqYbgfc7NRAKbUYklqOtXMb2n3L/oiCgJuY94RwyWOlY4w5McWksQTppOPG2jME+/pyljRUNIWHMmOVJaf/ysT6suX1kYEZRgQp7KR0yAsE+iQFaEjYY7FlmSsYxSYlNzElzA7gs4eQ7x6tCBB2pbxss03SJl56Eq7rFOsBfGlWMsN/8afazppu5MS0oJTKvcGshtzJhfRqbfxoemD/a1KK4KE2jb0TUnA7yeVCLJcUB4DLAUC3nxhusw3K5TdBOV+Cm5s1+YTuGPncGlzjd0UREp6UNtzWBWN9DdFKHfwqUv8+TGysrlxBFYXCefqXqDfePM1/Bw4fPLeiKaHaJoQOt5LJMZxUGYuBlXAmOxGhDIBrOdN/GKOgo/kIM5Qo2HS25WmIZ3Wcn9EimR07RUXBxEs+I7J7Nw1uBvpzjGtItCNrZXCxf9Am4OEvzKYarWW4DUdLWqzUWEjfxaGdkFo0KRzYH7aHi5paFIjned2xSh7xs7AIknGVNj008ao/hdwrgEOWNXixJtjnYVYTWhxKxcdxyBzehvUtl5nohfhpBzPqRwg7DVRr+mGtj6zI8Db9F03oaGi+vBgg6UHs3SWEcCJ+impg/QGlKERraKegmgdc0oe/HEbOjvly6uMWRUoKjkbZGpnDmuuOFKwLBBSTV2GIvbgLpOP3kgbChkTRgBJXvbqo9e5rmlEfRCA/qJLjHN/qYkSdZfXPG6FL4WswFMQQJfvmrb4aweoVjdUjWDcY9oJeIJIPbRcxOMKwODZ/EmV1gCJxwvjNd9lH2ZRjNRuctdnOh1CFuj3xWAbz80cmF9VfgoDfM/3eLF881BqEu7CqCzsmEc0zvId/Hoaw7+d1WoIVnnZFMqLYiHxyRLrokfFDl4gVP0VA+f8ibJdOxkH7yfFL1pPEE4/g4zTrCLjVoipRKlRgNtrIHMPO9YVP8bKRqUXfZYvVnEvAeJwSewWNY06x2jVaiXp+R+q8wutKccXdsQR+TdzKKRBKKEtVIlRPI9/q7lUt85SNYj16kxxOWd0JusMpkGJOz7ji3SD2z2KwSRSIfOhc0tQFb0+6d39ymPg6ZXLOFRtt2FXxLoVCCpG6fD+mzD6ciln0PbMuG0T60Ak9Q5fFy5N5YquQoMf9r50XJ6EDhBMudNVHXSc3a0ihAvJni77q18MCtKKwSxk0V4SHyKR9WTQQ9IYleFG+MxZ/vUT1G+F008jQW2fo0y38YMDlN0EuXsXGalBDZf3Yrtb1ONBjLoGNiDj5rK6L/w/mN6XTwqyx+Ya5U2GmLMQtnsraE9OjDCPciksyyWr2jzYIcE01m4omTJVX7tdtpMbnus5ibBFDboryjPK8wejiv3RP7aUuHIFg19r7wHqkUIb9XPKBfAKnMyRD3965yewX4ZGgQJ0It8bjWaRVQmhNao4v6or2A1wLyIm5SGEzkXZUu/g7yCEhxPov5d4lBM/IGPHVI7c+tr5c8ABK1XqX+nFdSFyVSaLF6juDWqkyEPYmil/gsMFYUf0hTy4mRK2wK9I7Zj5rmpJN1a8PKrg9N2Q0jskrogtFO+3qafrCEy7LpPI6/I6kSwhGNVQh2tr0inHRw7PgbKY0Wq6ySPcTv/And0ArWq/fxJPngfosoRzdgbmkt3NHzw35SIXZjb6bYyGrXkNA9KS9axVNkiWOODA2yEEwKxrbd7UAVDAzGZOROnFc6zsLHV5HNo0Bx8h8w+Bw8uje8fAyF3JsWzuSXb1yZESI3W6eTLzpovZABB1LUQ5e/7oV+f78p6isaCUOHQRrdSFuvNGUrX6NaHfzfngyafHtokm+WmDoYXlqyeweYD8gQlvRd+q7JJZhFGwrrai0y93w0RLKMQXX40+Pe0WSKtIyoiP0TnDCvuf4WKzGIK+r4QE4BcmXLO30g/anlURkFY0BT6dpB6L4KHgngD32Z2N4UptS1G9g6fC5EShjGv7SiPgoE1v8rrnrLpphaAGvtO1VPowvBdPEUsAI6jzAv66Fm2F25ZATwUMm6N8zy/42lWISydAOxhmaUxCNaow2cSntwWRFeEy29cFbeG6y4hgMgGGWY7tAg3xZcYFgEV4k0XPx3QG6ogUdty5qLGD1wNbtkTHjN/bHZM4axMZCVH2pqruKLtZUE4OtKMho0f9K5fXMnvpnZAH0/Q9DEoflsAaqcGTxL0JcO2lvNEZWHb54m/JpwDrKxQHVLrJ+Arvw1S+TZp795Cqou8SvyKEJ1iY6qOwa26d8h5IMQmGejTRZnr4rp7zbbmyhC0swljYd5ACkuZdyjmtmC6QdrrmK4DH90kUEwov5jJgdYEroiCiQXEsGZ+giYEOeM3oAdmU7r0tx4ljcZ92PQwR97hV9ICAbCaVV7Jn09Qq8oa09FCdsLJ1v3mgyReYhzVNrqJK7vSSZzKS9dPuBqoVyqk7/cH+Qon17hgWuTSz/N6dX2bbOYxAWJ5EVci9y4s29cclYBQqeq69saS4SeSqEbCMfCedhyZkwaCCXczV7qJeiwMb0ow6CAU2Hx7AQaDbiwGzK8mnnGpWn7lJQ2VVGn1QQRz8+ffpHDj2v35ziPMbxlfJEcqnBjVlns6MnBEPC1ZqmAvvz9Ec+EzGOi55nMP4KR8CM/EBVEYVrDATJtqjtrkV3TuTZg9huTfrBoC1l7kdwIzJ80cAkhm+HnB/MwFwNguxAfSIkbv/vHRo8ReiMOUzGIe1+K8bRygvT9KhVwfWTLU/atlZgA2tANnw6kJHJxBAqJF87Slcn49t0ZZ7xXOT/LqbZ6kv0y+o/vnmDfjqKMrAiftl5EGNY18RY3P7forhR9ZIMMK8pjFyJyfOW8BbsTh8FtzJvP7/JFPb+dkD1/7lvL3OXVp+OLbDwAB6W6+5lFA4wy8PRYlZafepKf4YW/pXMflKjQAC7TOyVyYFmudGSmJRW2sSJR1CQxqbZxIHor0QJo3YeyqdscaBNGpi9M9lRSMw3Vx6Pbly9Dj+6tTqRsnmKZRZ8XE3HjaEiOmkU0bvKH2BE382uvQj7vWCcHzSOpsE4/R81It2KzizfmSGwTs4MikPF9AQHRkt8kcfeoCXhQKdd6iIWnOtXAngEYy9Q+Xzs+bZkr85Y7nYq6vfgSDKVYJzG/zmUJL8yZVl08p85ZWgvj8wyupegXez6PCmPdDHOVkOcywmNwFtxjxmVP4QU9IKX9/D9W6CpMRUeBSRKMjWuTmjcI3pLQgOIHDMQ4PDZ6wV9cDlxWLIFJXbFPDNtjqMADR9FV5XOCqrih4jZJ46p/qw+t3SoMsoNJ2LplJOfzReKR+IwKAylNMbp5t6evIOYpk9QBF9/2fdL2AQvJ6CPJEuWQcIEhObcyrzSWnklQtHzwwQ/+Og4B+LsEt0DD9Qut4DUFmRxV6lmMZqIGuuRgXJCltxfg7HAcivqjC0BVp8UM6X8beJULLBioKidpAKmDWiH5E5OwA24YMroHUOl2C/XmbysKlmvhgZiSsnGMaMe8HGXrwSZ9ojz/B+kkO05zvZl/Qp0YMwvExdOjaftz1r+fLvO+F/HXjpKnS7t3C62dWY1ALera7xF0+LIgssOiJhOJH1WRtXBZjXi66xQ25qk1GN6pn+Zr06gmCNzJ7MVeog8tvC3R4iTQUW5TiN0jJCIMMH2iSzsbM8KplqaB1LBO7K9rv043QQu2UItzQFo04PcJvaMQBkOmYeeK5GXgsIqtKiyOwEmejnz5TY1fRxXpV+/EEasiUWci0C2N/jxE0wqzM+/p7fbxThNBLIH2RyTIMExccDDxv2G2mHdzutK/QPQGkS2te27HST/WlaebpBMHLIXUK1BJAawBax23aYG0ZX0tVe8Pu0TIvCUUspeke5f63IDwIFI5fXgJgwFnfr/TGcFabADGuhG7G2r6ojqOExc0kBn4096alxGgB9uuxf4GWedpksXPoShp3gttdCK3OMPqHFdRIgEvWhhmmOvt/g1Tc4PYaUnQU7w3QRhtZuOFtrKoio3I1StNwC8WfQ6Q8lFpfIiJGONPN8SJqd8OMM8DWENBU+n8fpAvMri+PWdFplnsnDenWiywpW4Jr8wDOLNS3OeehccVjPmgp2CFNH3l+Y7KOGgOdawXtF8vuMax2KiDsMS4U1QOYTMv6r8iW3DFwfg3gZyNFqs0rP3hzngl5Lcy3vn4pZc1IaIRKw39IOzllfUywGA/5QFX2dcxPhCTwqxX+icQHm9cIdvqe6oNy2QDmAgX5W7gagulonRpaApQIeSTmvPl2i36dWqnQDeTceeeqmdPWqqUh5Py+HgJJzYWc98QNhF+Ll+g+rfs4aKVQLVxjheTDxrsH0JTv35SPv0+5nN+6LmmAkXr79g4QVWr3+zxV61LrObveSeVWD+7OVk1kkYZr8bI6yPcQt0haSxYYVRlqYMpzyw8n8L9RyawKTa+lkYjZZjCWtzRD4TanAY21hpVAOIwOhBXHlsig9HJ/KcT6s0ezAvgzEAqCHD4qQI4cK9BN8gwzWk5eFOmUx+3mTd3j8xYLX8xXe22pxQhxOBkrhtdpTgnaw7MR1t8spphsFvjqQr+K/AmKJy1EFPFXfJWtvNnJhNOB2K5KVLF6MFEwK6Xb2XpjQMAHdwjDhKFN5dZfOG6OCCv5X/NlGlEyRi0rH6lyqpqy11r4V2g4pdpFOcqKbReDgyJifCPmZziMK5AIXQMl2/P8EiCRb1QKLx83DuIx2tj+N58u/ZIzBiTkzCnHfANPwe1lOkQJRWq9gDUk34Ba7FA8buT8YZZ04ZNgq9lXlBYrL1zwTFm8gWC1SbpKS09SaBa96qQ6DID3XyWPdTBv84WbPKz4V/ky3hS5rhEa38s83EuEGZ8Bs9DLfJkQOV12XEyQYLOUbEyu5m4+H/8VO98piII1PSqmdGZvAx56x0DH8yTfTFuI421grtEqAmvR30WCsOfUw0HPUDFdmb18JoktQmeLBFEge1RIn1mRMQafaIksW2CM1CdiyY7Y/an/NX93EY9fZC4Zgc/CP2UVg+ypStInvgbdPd+h7EW8+JTCgRuNxf+o9ktJ19Z4mUmgJV3JFfhClo+2DoOoftifQFab9yFecSYocX+Lp2tNiCJlJmpmQE/p2dLTo3/ncwU5l3/cA/gzRVp4565tUiYo3owEK/U3a0Ht6/Bbju786eJ730KohblBaNaBfaaX1OTwEa0X5hvV/lDoGXi4IpLW+rsyA8/UaaOtAdnDFIqqYBxlQN3SRLXEUEzjzQtJYwDedEX8nSdnb6ddgFdXhMuJHutwl9fRTQEI623BbCC7PqT/Z9nqYZyFd2lO7Sw7kvMGT37DLwKGHQX9mh++Ye5qMhBCDGGPyti5KUNAXXsuxLRjT0B4V6gNYldeY8c2wypf3gaoOWwwNpEm2p8iua1/T4WZUVLlyPLJKzlFMBRp067ydeY4ltR3IqP0B8hJSBZP/0Bxoe680/XkoWpomt6KVxHB0gmTpuCRl9kBWLzle/UzA7CSMXByAnoslmaOQqZAy2Mpsqpmg9INGhqIUvLZUnfG/ENbuS7szyBw8kbi8J/6jKN4ZC+oHed27EhWRqMO4NxCKWeTjwTTjon9jVExXJbDkhVhi66Z6TcD97jTmiF66S0yF5VOZPX61Um0XZSagzg2ddcs+pfd/RqACb0DK17KJg+kf9AkCoZGLiXGxn0g+9qqxR4tNes5ZKPRA76l9btkXjveHKKAQPvmWaDY55R3kXgxHxeWJCUKwytVvLWTVEUAYtMRYtPZ9S7EKQmI/Yvx0pdWeohGLSX6ai+HR3XyMXGqaJK4YSq9hkSE9lGzTTWiQ0wKbAY1MRLQ6UpAb6wDFf5hEljxGMM2sXPjrHaXixkZLctKs8MSsDjcFH344F1gvp7i2ya+WOjdwGVDwHJNHiFobPzrmvi8ukAz4V4+u0XE7EVBWl8nq4ChG8O0NsauVPwzmICpK3nUvjtpfEgnJpROw1gVZqPGOKXgIW64BzfswsJc6f6EQcsqX6O5fP/u1nGM0OHD6Zg7Bz+RHjN7L2bG+DKzX4CqBnDKs7RODLmdldexCQGleoj9o/Kdcx9ghnyi7/t4KmrHFKIjWdSWdZKaSnhZbCDJeGlqhs++/RuxLHRLKx+NCBPW6jwprsc0f9HQsQJJOnhRbt+zDcC2SdE6C+HRUdW3GSikfuYyh44le7CbO47BG9PKBHYoL25e96Vpe3ljJPcc89vyUqAYsfDubW1BUUEE/algOv7+PQOG8QwH/ttHv2eaNkNZ1oTIUPznSteLrQd6fTJX3ULqC+fpTc2PyvcQq29Vu3hVVXfBneqFvxCmi3rwn8BGFZnFiAIAon3qm5/WNBsItzeYQ7dggCFBk5sI2D8youGWxEwrr4+UEP/P+ee/W/k/T07Oj0AHhlJY5uQaEKgNnOBmfXpNTtM4yhZ1yuVVh3bubf7o2PbqWFebuvtk7r12WuL83kqWN+VOmCyldgtgPUA8wt2KleGQcFjtaQNXjCSSjOoe5A4GqFCm43wCtP3a/9aX7bk1pyXoVIYEf7kJhmtCL8ZthV3MXw5zMSQCeRgLTwJh3/el/H8pW13v3gVX3kgILp92uJi92iMkb3LIvtsKM3WDMBhRZ3o8MW10g1DxIgDKxwl21Sw8lJZQ3T5AFzp8X0dfq2UqFbCL4Wdmskh1t8RTZ8HJcjHYI8oDlLcfl+u4SS9OVLG9+nJgHCT2+ei1VYsBqQOsOnFRLd0Agmf4X6eorn5x7X2DM3bT9/dI3YEp2u0Ys4r5XWrZDHZ4eRDdGXn60PdmEPeu68FRDkW7Qh+roObW1ONtakxyuW+O9+NGwb+Q1iYR+by44LzBtPL6kELiVSDhWTWLYn/DH5AuhS930E1y2sILHtYmikeomhZb0MGfC2MuwdtSE7DDPRPZtZ5YJVw0cqgPxT2O5agPBxpzkc7eamnIsSRjWCeE5Vq+h1LYgE9NtY6d5ZRjLr+mVxp1Ar3v8+aRqGzjYhfEKgJaWmGI/PDuWYr2wD8P5IeNUn/Bl2YZclMesZpS9YftEp729sSOBH34THyeXavr1zu4cXQlfAln1B5aLgU/I/I7ig0Bwo0h7XxnFa2SxQkjy3WzmBRwXXqyfZh9WKd4rLUc2sKvsaeY1Jg6stWX4mX5MgYaF3DjolxK9v7cAml/SDxxCZYyO6SHMxif/EnL5pJPWdrXeS/e5wXbYkDi7E068/dDxdNb2p7rpQRMRTNPSQDlNL5UzaKD9Z51f2l0ZFSCAayxUl/6Mvh407TSaw3RsdnxkCAykhFfn4pq/4azyut0zf03RlfuGJI+SYWg6jvNSdyyrUllFsPxqB1tRDBKDAmvaLWKKB/1b5AgAgLa0fZcPtPbl5G9T02pGozcU7I0nSTBvIYxDvy1x8Soit9dTgFoZZL62WWlNrg8Jg6RnnChRUk/E5PLq2bkTxupEtKuNnGAKfEim7bUAjkwJKe13c+vHnLfWUoalgCgogLABVH3KpxjyIFqIBp6jiT/8hMB9yfQTIZzrUnOxEqP7Wu1OT+i2/wTVDoIsuLH2I60FC1kC+tb13/I55EEWWdxzdY2qIgVwEOVkjIA0nJkIkLZp5Sue7d/aA/qC5ObbavhuGKGZYILBArsRzuk6z6hKl0+39H6YcdnnCcm/snPeUNtxStK37gIQH4tKx2kriKAwDgQnwq/IwHwUSc3hQ9dRccN+ilGtoaCY6ohIUykwOEG4XKDD6NzhtWl9i/6pA49Xrq4fC2Udn1ecxrVReq3PM7TK2RYCNDqLWCtUV4vJVCyY8Avf8sRCVKAn3uXdRzKJCZIdIQzBmBGMDdB9wRuaLbhpOCZgxtWqQ8z0mT+DP2B6a9aR+P/PTcDxHEXwlqqmZc6boVWLHTxWvyEomw35IfLnXou/ZdxEyV2Cqr8MEXfbjGTAA4KEeQtciELhprD8oOWYT3iFw+nJHQVNz31kStQvp2WO/gUko5QU+hwGXyRJ/UsYVE+SA1uayZ6QlxWWNXUw1SyWlvenrH2PLChNoHhOkBzX9mbVGUlpbfUS/rjHLpZ5OjD/VdsGMUGzSoitBLLJqpI4/dDQLvYUxMiMxNSSPnXmeP9QMPjv86ASmE0/cRMOSh5KoTFx8IhLZP/7mS56bsQ9F/5uveCjxcMpX+OpdY+MuQifnTXK7I4BryAm4Bjw0Kg2XHh2rghMRPOYsIECVbcj6pXcmwIQSYbF7QTzT3lFyoA2C8Nak/bc1QP1B/oZ+2/Iad/8Exw9B09ay/x0MSI1R4Y7Md9NWP9+MVz9Jkg8FUnTQ2rBKjOZQX70cOzXZ74ggrx+BzHra+9M5+VAWBoE7oDN1/c5cJKaYCfIPaolhyS3xIwuRfjGL6OaZHdLlRvcYBRlI1K/G2E2GpUTYY/wgVoehfCqY8pZ4UDTsFhU1GOC+N+uxiS9JoQI1+FyDMsgb7rJZO/CVMv6o69iKnPaxPaCt5+c2Dad33dQCAopMdsN2cItE2/tRAw1yNg7nVB6jMI/87cW/L6RF7aQdYj3aj0mNmOp11Hpg7uXyg7WogCJuY0CdhHOUZzsuBVZ2SuutvKRagv55Zm6sNWRhIDtOgnZy8XbEu5UtyvyNRc7qTQHBEdYiNwC54IX8Yj3WycAn5oNk1So6Uesfnti9OP/FrqhBLNm/9HVzYc11WhwG89avztTdyeGv5W0BZCYzSrQOHkca3EPdaTF7mnHr5m1KJiRytPACXdpcGrmuiGXIiJQMK7LWbQwkuJ4bVP1KsuoB6N25vHQhRANFTqYmtg7pCHnwx0S5qVVBjzynrSIV/IH33J7+z+VnW0cMnfHmah6chzLSuRk3gJNIyWdVWLHUbDn5ltgKX1eehfNRF8cEhhXOMj6K3lf4zzBEcFxb17JBi2r1Q7nhOPCGytjWedKFth/j3hm4t59ptjIV2A3Jq8VkaBqYGxnr4PTB+drLFYImAk7WbiqY3A0cMiNPAI9UKz+rmLtLea9oelJ0Aw49AlmN++MdC94NBmphrDdQKz4PF+ejnu+HqFqDrETUQiyB/Q4hJmu4BG8CYV1VKP5EXwLZGzQgMRee5PgGOAvnoIzP7dRGjBTkJmfMT/TghPylI7liIUnb3+9ZtOvBJK7Ji/DtCGR4LqIh8p9zE/5J6qDWiq/WZb766xKTtuh+hXjFoHYc4ksC9cNADD98lVrKM3GyrzTgaSRjLSD9MsXNv85LQNGM44eWU2zBh7w4QDOSVCr6vR7SfcyK3sAFZTjmUiBRvngQ7fessaBGmfhOt6X2qOSfHlDCVg/kBokjQoJGbwx8c36TRMd66/QEAze85yotlXIyy7I1PKUIzc69yO2mQ7Ug14zdug5E8sGAcuaNvPiIPBXHpO5MlSs61k3UmKJYxQI5qJb39fT/IBnyzKJTRkS4DnNfj7U95XtI6ePkO6+1TKPozrLNs8exJ44Lmu8buiUJJ6p1W9NqaHB9zmsY2bTUff3K4veCGXQMwMZhKIA9DVUHJq4k2IPjg13iOIlaCcFwAS3Zq/OZTa+wMPQsFiYw6iw+dfsiJXYguKWTzsip+PKfHpBJpJ2kVEW75O4NtARb32IpxRScSxTnfql9aa10F/TBWTmnVtOLvbXVXOnGel6My2Vw/yXv5eUNxxl+63hZY4mfZeqDFFwNn0e6awS3zuapdG3edbPJJD25ieZ2yDswG8aGudMYdt72I4Al1iSlT8LhfzvhERJXyTQA4Cj10U+JAzlw1fKAvOPGta5QBQiU6tBAnfKkFTsP5E3mG0jJ1BzJn1GtrKkwQ2SXn6IGAjKrsNH1DfIxXo8YtlT65gVC7QyeQjpb8uVCU2KUIrmW759BNhQpp/SOFhAzFz7eoL9Ns7URW1Y4ikDOOmniMDaIYptSR8GFmcUsLiaH8dEq0BozKKnD0loFm5YMvH8OkXmeabOvEQ2eN0KrIDBOq6W5xlsKzOVwwk/S3v0sNt/oiHzbGrD40FsDgTECpKuk0p2WPLjCCQvvtg9cMYoi1m9MnoHJdxP7dLmtZ9SFLntPnVeQ0cVvbzQ5h8zvH87rz2H/zkTrZ80zvrXJo+6Apa5cKirsAxzmpW0YSoPjCR7UKC/UtE3inhqr/SiiNqE+a5TpwDApYGMidUXwyMcqOTEvecZWR2J3lvHb4kNpI0qlJYDkraybyf04TP+kX6Vq593KIzJvVx0T6d8P/80p5iBja/1Yeb1Y6HGb2B2CcS3kaWNXEEQuyAa7GaQUhKSGDSIYl/P7T+sco6qOk612CIT/HJsNfB3tAyOdPkXy5ckI4Gr9b+D/DOZbRQKkw2HwVXSMZLi1VFvgmRjakmIvpCJzhWvF04HbI4jICFwRKSH2Yv6rMpQD057o4v5UzWnm8HLaFCN7fvm0m72BBoVbwfn/ZGtUvGg+1ZNkpfmk85nS22+2YkJNYyQFoSIDKpi50/4JyulgFWZ29MaXnzVvAD0eLGuYiM20e6ZQZUEZ95n3aadVoXgyd8dGu/b4zJCYSk0CcSOhJQJZyeOApSmoFeskD0deSqNBOuwiwDYNVr2TvgqqHNWG4FPeOOVpRw+cJCR/EgssP6C1uGu8Y590aPhjGND19aACfbr7dEvoM0bo/ImRTQZy3ayplHLz/sp/c3F3L6MFXg//TqIoQ7/jej+VUpOZgnwG/YoentTvca8xQt5QyRNgme4A7uYVRiEXElSHzFLNxvjxReuGm91HF9nd9P4d1K/dhG8l9Jj79rZJggjKlOaknftb39rCLQvfqWI/+YW7HNPKJ7VrplMmgtEAL5+rpZmnJmYgpBBSb9qJk9CuNvVKte9UVSbLKvtYThC0Vull3Cd9+zj2K0tuvS6YqseMtPRgxZsRKSVpDsxmF9sSuONVP2NXmFHQekNiS5b41Q3RLF+GlPLiDg3t2KD0Cu3u5E3PLypzFit7wnLTvMGcFOtK1LElXcns5lCkoKKRbqQKcDlUhA+FvasdU8mR5SgeVCAAwa8lcnFQU68v8Sblsd00I0j515N9DU5+zT3mTkUQCYtwfxkHeJ38pnlSM3r+kIiU0d9z9VWHWqrAAVyHNhVY5dAYR4qeo6Gdv7ksMyiNHuiHIHRdelqbQWoqsGKc0bzsbHaaQqTIJg1AOaMqtWsEfw2Fs+u6aRIVb6rd/KMhDzWSdfQL9GDfWSw+GYznUS+IycABZzA42uuD5eGAJeuVJaQcZxAj+4eZ7X1zYqvTJhFdFWHYzBfSXXXA2wMXplcUN2UTWgClAt9GupviZAd38LO1oc+NVVClgUY5V+ltvKV2wUVN4tj8gKnR3R1F4YHPVfil7sTzd6bbJlGt42vBZ658cY5sRwcUAJM8uneuFFVT7KSeCA247/Mtmi+O5lckVGJHy+rIM0IdStlGFOX1yk0wJ9zr2lZl3U5Lg17iAPFOkyzde/NWGMyfHcqPE+mJX4ABx/FjvdjtSpZFuIKxGeSU3aUtG2hIOCCvxbzr9s6jBGqaDVTaaobRRCe+p6celXP/Hb3QPlhILnPWtdD4+STJ9Q1ruu39SqFhvAWXBM52TU6bo8eM2cIessvUaOXagb97XV5OK+p6fsHJOOwcTagDhK/rWlYjoqeAUVLI2VHWkarJA9jvt6FYyqOwL9laF0/20YYqQDPn8Q+erYTdGxY6ZcH8QeGOdMhMHucKO53TDxdV5CdHd2rdtUQvczWdVr2/WpDhSWe8Lti93kVsXKtQTpgFwuYXIA+wdSFm3OHkkse7c8FrVp0UZK0CjLj9pEu34Du1+DZ1Wzd/SNWEWAOgSCDNs02k/Ha5mLQKwBWamnSlhBo3rMef2k4xbLUqVdoG/9Xi6i/D9NeCSOcWA9mn68HfH5N0Unwp1RdD61iP4HUD+6RSFM1HiDbmwlfwUN9nM16M7HgrcZN8vUIoLqI2o04mrvdu9nRsFIxadOBeJwb5VKjVgQiwDUBdkiTP+2nYKEcoE7bJwh8c5ILVJMTFgrzTepoyh69fwlHDE7IK9Qu16naeM1AIK0hmsfoPdJ3klfC3WQeYYhmxdNKmgjtOVCsAUA5GBk2F8cLxIW8xPFFqMh9FRJbqvpaH1l/2ek+gl+HV3gRhjYPfaFuUb6B3S9Y8rPpZzoOYmuID2NpOA+t99W46K+3BzExnnlnWar81WprpVvR3UY13Sft2CIsLblkxOtksn7ZsFO7NuJqdgqYCscsdtBCYRkqbHHDtWu1h7VUih1RS7uRpTkYndhU6EgonpsSlE20OBLMRhkdJbwsqd2xpb81/wxRx56UfkaDbGJbNgOQFm/pmLub0r/m0SA2R9nTET5GiBqvkbpj9D//ftiGiWHMfYtac6gTHIgJIY3GCIF+KTH+cdV1YRUoWz90Ifp1VTO/IdBFRV4vWZqvQQ1UfhREwvy+wL7wgRi+TvTFapG2OHngUqZrgJPQKurOzb2R7cdVOlGCtbROTA23lY5uAE7dW9xcm5tAj1lAXaJ8vxvVjlHK9+LmBBpZa4EJ9kn/WKp/SHfDzSAIBAy0n+Pu8BxERGbRT4EmAAhavxk+EprlAGTQQwg7uEw1icep/fO9pzmZfNIDHsUXZF3vgdnOdKmwuxM2gjSKYcODpzDIWzUbR43ltkNaYONjmvpnSd0oM9bOTHt5j1G5Z9ZV1cqDmOW0ShDlQLbxP6P45G+JbcH4GplYKvz4iowtwo2i8E0oAWKKJRdm3M0Yu2WAPSJq1mf6JrRv0cZpNimG2YBSFJFcRdxOhAAdvWuAG+C3ITuW3bd+toYBQXSqjhjpQYcXHJyqmKw869WBX4EbEji2utQaH0Vm9tWsuMS272HCIEkkMS4bXQYE7AKk39x35gz4snIWQNgWRfJDrx8hewYzvfm4Uq5zD4AorUZYqyfHphbxrWPGUvSwP+4BNe3ulXLi2r0DfioZkbhFV282cyHgJSR+6FbOdeQ4S4c19h+PKByq1uXDRSXC7FGpLj5eQFJg7/0hRJXAhxXZ9+CHnQjp7jqGbwDJm0P/BcF0U67e0DJrFxFciREgoPhbfWitArVGC7xf/P0nNHxnMQrn5ZtmVO/5wH79t6ZCTaiTvLdMMyHML8ymubVWkG9ncX+1ywARre/Tfo+5IUvA9xb6lwG3F3kKHv/BkBBQjhH9sgNLxNck/k8PiXy5CJ/66AMskUEaMRJMAFfz+qdwlaBeuutGRjBuXpdR4pFPrKHmmYfQhaOLpiqVw/zhAEMIyhlXKPj1vPqI46Vwipou8MBnb8gzVxSwc9YSHMPBj21VlMLZkwSbkAuwdIIkB+eNfvTsL6Kow3DRrl3VEdamoTFBD3CZigeaXlrYtCazdjXSQ+UxBECLqE85dUz3Qh7uhC0sbWhLk96sE4pnrFn3DPoYhC/2aqX90sFZH21drBs75VrZGrGRw96FimVnkw8O06hYfqOInQPbbKQdBXD/i0cF1SxXtjMzUJWtE1VBoAUiTtX8wCzEMzzoTf4vODBgWNX1bVrcoXi0d4zE3mTlO+4gRm9Bea1ACC/cyGIyKRivrTd/pZFET47iGVWMHgJnENDxCzoKuWFbXFCsrDFKKjr3PS4S3UgJ/3tO68mF51vnkeSxf1uABwwD+D2Nh5pf0YscnFkUklE7SpbyJzRSj6NOqHwb4vJkHsFtXjDBUukvpv43zwB9LLwBR1mnvikG3a+r5/lzMDOtJBI3eeD8OoSJw/QpfDVJdk3efVQpwmD6HHI2GUtkPj6Ib4unb88jnB9wZ+lN1YZjvcOPZWUehjSvyjoq/+nZTodlPnkwLpm7Rgl/08w56RcMdn7ch047DhpLx1QIVaVCMClz9k/mqfDibmhkfz9laaWCNbxApnRgKFtxI7Vp1XzyYnIXXDCdfidsWJRqQLw2hjcB566RHVpr8vx8AdlWCBTwdjzRKqTwC5RKJJLyEf+AHhLP0uyCPTwLrpqFsCZUyN16QF3Ue3UuRUcAlEBIWaBpDPlkHNOQyPh8LGedzA5XewYFiMy7FF7MBHlqk0Y7WW2jTzRh2OuASh3Jh4rrxgyYFIEkVnQJxZud11qjaN07+EjX2uMh1L6f/bPOSBvbuatkeWluk6N4JFytj9z2PCkU/OO8A4keCwssMj4Io5XaAJxgdWJoZbC7Tj/bziKp/blAjuS4vDndzW1PDdGZ2H4gQvhXChQAFnOctiQGCO5U7W1mlP1t+aP+LXHvykvETATDoOL0hnj4IWTBDJm7/XNX/KGxPmuf0pVnXZ08CoklGMSjaxk9elKRloLmjebt6NT7flbmMprU9kpzJIFofT2I8Jp61bEtXx8gSY7XRMkr0JCKraWGhE62bztRbcTXUk73UHEiOFuDEZe3NvA0KIeAe3mKsWfJOzdlfAkyH1w+btnHw/U8fRmyHJR5KcLFSxq0vSK8/dCj6+7YEU0GB8SW+afmXmS3AlT260CzxMlc1yxgCxqvDdUdk/zEoHSLhNxW0oqVULK93rRXzJHafBtRfKs2cB1dKkvrinHB+qH3m1182f6QX0KPanpQdPXBLBeLlrHwWuHuoja4zWvpPYrTy7s4r9FV9zZuyHKdqb0Wp3S26oqOXb3IlZoZG1DfLEXmOah6M6hAa/bWt6lF7kd2xMHwH+4qn17QB2YHHiDX4O1PGJU0bAl+DVyXr2+C2hp15lhsWSrQ+GSB2gyNSLqPie37lwbRpfFYZSvBFAkdtXolaeptvAiLM7/LuzKF8mA/KGP+GzlqZ1iDN28lNSmYYFHv/iQWItHwRzfBGJXtaS1im9E0y3n+SiW6OYg80xcs4h0Q8iGr4CbaBABNZly/ig8NrBC49tXFoWZVaEnP3MEu6zZ6QrmSZkBCDGb5fZDpBQlUI2ecBoPxoI4lIak3y0EjnEVACsjnfP1XU8BSpobOqZRZi/LEbIKNGnL2XL9uf7cP2U25oq3qne9ud6MCcqC7SHbsYYBq9CH+jvKmFkbwlEz0Pqbd0gKKiCuibvJnxoD0irPL1Myg8KnqexD+pfucUchtH9jzj/xzXvERbsCMq9yMw8ipKB3cfRxfa5HTmUNapyXuzIJekjOrK856oU/jEgD9Sy/P8SZ8X5Gy/bp/Wl6uI1LslePH3ziYYu4HkOeWPoG/5QsfvVn6xpxCn6A2TycL2owell/EUskdLlgAsNUsRwaqtj6C2x5mptow8hwWUadoK9wB6eykE1vYRd2aCt0hSIuhWdNAVRZwp8aucK7fLwZ+N1j2fucrfQ/6ilFfgckOKRX4vcyBWqsqceWCach4pfPk4GHY6Iav1zvaX5RVxKGfokc7a2tjqNdpQit4GtzgnNx+SOD80Hy+tDdv4kQHw8rlNI/8CooD4Nm+wiuntHg+CydNXDtbViCuAZl1Yc2SveZKTyTf4uSf6qRnDnEN7cjk6hUx2HdvdyMF7UMb+N34CiFiRbEsQJoeeqUDRWc1Hrrd4ktOEWEH6uuqgtXBg/NPldXarew72JMjS/LZX8EdhUECQZDko7hpOe0vtnNyyefV2R7QtfgJOn/5GlxGBMIWgII+JBxcNpkjngy++p7e4BUDMbKqjKg4vpzu2I4rl66vZFqsrkvyhlEC3iICBYoBcVJnM3EqEsglKIU5nTQVvEuUbITEsr34ALWaQG9rmVr7kDsxArFSOu4ZR8ml5HnhtV8SEZD8SCxwrmqGcvmK7DYZZG5+vVLuluRjommJQVaFAZrSFV22+xXconnJuPfPw6Tef8eXdjFlB4Gsm6iAT2fhHiWgh8I34FWs4d/ATeM5s5rlCKqTYwYNA8LWwgqQbrYMSkQrKQ5Sn47Z3/0WhrF3EQ9kN75x2ldQ787wIvokSg7gFPd/Le1lGqPwBWBxlfIf0Ijs9PqdCSnh6vS5G/vP1LSgq51HX3GW4e+GIQdkvHp1WZ6kxGGeqXQFbZE35vQrUVss7TGml/pMc3tcg5wGiOz0ujIGCfoUAmQ9fk+0hvRs/EO7xd3KVcmQa7VNaYFlaQBcBHXyruCyosp5pT8pg1pIhFuey7pS2nA5cR07iW6e3/bd7N8l2BnpMQ0Z7y5z/62LWI+MgQxVhYSGgquvD7yiso2YTy0K2Me5gy/4pIY/fOdI76eOf1fPWtKJGk93y0UDb9fYW1QVpx+CdtdaUQuI1h/EoDjQ3KOBOFaqG1ZLEmQZStMY40f+GCW5eU/PCLo7DFT60GrUiz2UklAYvAekyJ6RaaJC0q5KAXcq8G3UJnDLfCzdX8qpf+rh4rjWqaesmZ0pEskSrkz+t3/4C7+pLGyiaXSMRzfpTamKmlJ4rYvuU9aAIHzwODMZnd7BRMa0q9IVaa5w55twqqkgi6ZEp3HK0CEwgQpUK5ELDuwahzqaPIVw48Iq28fiIkUHjOfSjTu6NnbkJj2jd35O6nLFMAmM86lfjdDQuBqKVLvzoZ1vD5e45ZSfwAwStzKZyIIkmVPsH2hUAq638X9ceLEHSQBwjX8pW9H5k2NEWzZpC2xpqy4L0PmzY2DzacooJwa6nvUWCF7mMud4h668xPwjWoILL/hhoHZ7EPJyVKcN1VmNSp569ZRVuYlwfYDkRnimOgD/d41ewQb3ul8nGWcyiSvdXQPFl+elva4W/7Z3CRAhVGJtuXUr8xRbQOVf5h5R3KWyIbdQiJ0+7G78ciuAZbKzixA9fXIYLnhlweA1b2rTy43CXpnKINYl+PfRVd9zqJPdXNB58RJxJ7cBD5Z0upLkJJ0tQBp4ES4vcAiS0Ea6AwUqAxGnxV97VsFU3cZigs8dmTO6+j+fbLo0MF3tYyiAkk8D4wkkPyQ0vSYGgS2w8gpkCeOLTCSbbSiAI8FCL7SR6J7ZPqKRSoWIzzdk5zAJtw2VRydWHZ9gxpf1DQAQqBegLLTXA0JN62UpIlCF1LUZIvIsCwFDJYs+dYoTBskjnoB9JAPwJ8gecwXfWUUmxl3vodScQ96pT1OPXBLOyGzy+D93FlWHOSudxmLDO7qXmfep1YfsENVlxeVoUEOfYCCq6yYZ8zdTnBBEkk5jqC5wMb0LMM/JPPJZIoLF1Pzl0hy1Z3F57M98p/9F7q2ZGe8Fp9Hr3gmyIDCmUZswdOxqNV8Jsic5BV2Kx4fbFOg4Ajcx9UkFneCBNBrowCXSoBDeM7HK4vj1CicMQG6o/A/AmSJmAeJkDU9Sg5YeRaauplS2cG400N+ut2dLZIOqap6+9iuN9xTCMzeDjN+4QXqMplup6JPYuHP424RIbCNiTl3oyA4SYzC2MQdN2KuhzDjZS6h9R1wKTVIDOtgifAtyvj3iajFrNBWwi4bGZ2j0adndmTtLYEAyjKHit95+l+fmhHs4e9bzh79pJztLIvWAfZHmqHZ8e7TsNHcxgPPe8eeK4XSkg6XD7NBjfdz/+acz8OnGDgzQW+3SOXCVABOWzLEOW2oYDTZTkoh35X9lp0LUPOOnZu/FUIPPEpSnmIBiADjcCHS58v0I/vzir7hBjfi0fxLnhz69xBSo9C/1NQB89XNJCut0IGTnH5lJuloYkYsl8wqKU0iGtei7gkmAJonHOcrrNmfkMizLCmjYeclOF3WS/55vQBWf41yUt9Q0m7gYVRPfD5/zxdzO1/xQybMBFGvtWKeq8v3sAq0rhtomQWdhsBrPWdKQbVTytCskc+jpaIVrQHO0w2EfyICIgV67CpXLMM3zgJuU38/m8O5zj1tpAIUuE7Me9vBAC/KSZb34MdOtc6A9aJJbuD5NjNaT3apXla2bXs8baRznPfSsZ+aPw2aU9A9K6p8izvT8/gbdlnBGdedAR/T/FkJNI5wwF2xTIhr/u4V720NtYBqG/ruBjy3MgvXhgmtREB/Psx+GWzWI/ikPEAmquXUigKi63/lv5YRWr/upTkcsZ/mughZvQ0uY5FgEB5w0j1CUsv3f9pgBUrmMUOTSwAMV0scgBfYZ0i2XVK3cPe2WU+VaIRkG+zssadOp4u1/Kg3OBMPmKvLJFoLHWVqwWY+hdv8UIVJTkYuq6s/YFDgUW6zjiKmFryyw1YN1jp1iLrg61QgpKIIGln3MquiY9C5+/5cU+KCD5v9RgNw7xl46GKfZcsnfl60NM7jsZssgkik/9UxqyPxzRNBfnlYJWU4oZSusWPtUAjKi8N6LsgsNZ6SNowwaqh7ZWS2VlID9Q+Jfmk/0x8KX09JhTTh8EfW8A+uM8wI89YLSWlx4EfUzMP6XCVTUTQ000WOjBKUjN3zBXP28GjMSI1SYfXhSnFcvATQ7fjOoqnXVdAS9hwjU6kb2unLqJdafmSZXMDAdqCROEaONT2DinWA3v0jP6mXBHKMDQrU5wuw5GSlmwUfCIy3TzjKyiRoIASa8mjTewJ63pltDsQlY7uYkBzCJQZN9UqfYIl9pMDw25ySYvKQ53+Bu1PomAnF63VW6w68z3JDhvtWv6MLDj4SbQ1tmEPyqExT1HpF29egNKlsSu2A8d6B0eBbenB6REkbZ0ueYaUGLLCol4vfctWaAXwuKQr2GzuAr92c2PGyLZgy4RwW8rPCzQ7DVy+r4CKuKKUK/+ssRGhmJySylk1eFA5XWLD2zT/rZrS0I1KUe5g5pNIQTHLpk89bPvwoIC8/oeL1Lw+R2AMomZcQ9WiVqsAvm/9pNln7gzl+0h6x1vvoVJSe/7jrZRK7CB+qSAcqb55d6VIp+fLvO3zDzxuZAU8l6DiPCMj71PKVazilPCkcUagBC1JLoRpTO08WgocJQCdLvN+GJ1zWcx00dUzuUpTjrmxCipRLQHEGLZsOL9ZOKL0N488GX4BxrG4lbCMSSiwvtoQvrgBtSdQ0aRCux1y9KKvJXDHxsmJLJJP0KLsc45M/CMGCSlL3Y2wqvNYklIxuQNb5IqLEpifLAB4aimsNmVEnnLT0lVzME8MieB6WUAgzdjLZWZfTdOqyCxA/0Kvg4S1gM9X6wKHO0lQ9odXwcQRFH6K/u5gkifkCEl5FWRGmYMUMRH+FggqdLrFqof221dchOWGoHxQcaFkB9RF0wpRFYhBWujNuI5n8vSvZy/gqGmlwNFjibU1/3cJQRF8XSWIvuDJwnr3zv+zQOAD7PIm51N7P+7AOI4lqp0OsqcSaCw8Y90hi3H32DAXpqnPE87vg9VrtzK0o2IDBjYa4Ow+P4FtFvJxaSn8zq5U5Dd9VXSisZSByW4G03WNKGi0v2dZJSVnQuW/M06pbtVgjJsIPAm1p5REoqwVtZy4Ze6BPMQ3oON2qyyeXeTmJZiK3+8di7IemLmpxtesGAXBI4NUSt5k0/DdyCntZJ7CyKkgpXhtbJ4B9xNte8up+2VL4d9dLqJ7lVHntgpj/Xk6C3aAg543UvykV0oLH0SkAEzwQ9e4OGn4neZDuWy9q+PreaH7dTmo4Mlt+p7WtUXbvrrz6263ZfObCjj74q2hizx/fzlCDSlxVwdFRBuxNHm0rSVC2ycSjfpU5JnluTk/WMbXJbhyWHgxm/wz/BIQ08uyYuKAd+BSMj+G/JZZj8zGC8t4WoIywA3c4HfNemkUcGAwwcrkFY2R/AThH2zu9fphuNYadINnMWfTFKbHTkwJvGuQhbWlaxvRW6+4xtb2H8mQlpicMWTpW5oBVLlAlgTV/RmUYqIfxDICT7GEbERkM3yPTVQLyUI+Zyg5Xg5svUlygT8QzWArv/+s3q00GNUKNn7S15RrFfTj2doXrcJw3VOFGqLl3s9hiDZ0aSr1FBeOtVOi5qM/u91KP81BsaXgTsJJSCeLghqTn6ONYSou17pPMYG9kGlzoVygKsuOlaUGFdov9IJ/4wSljHVfkW5v6N1hhHigOInc75NqO67uPedNXjlXHNpP10wuoO3uAvyYWEp9pN4fUR54OG2oXQhoVnxf4etNtJNZMQPMAo8I/YLz+NOiELiKD9YUZosKY1Iw8AxtFCXU4OdjvZ8K0RtDLFAwCZeKh4R5vAX5IkL6i1L2nCMymOXbmZWLWmeZaZUfwUvh0eQl26cvjU0JwT3I8SCb3U6u009OBFIj5e+XEfRLP0nLLlQZIEHfSSlJPPalH/aV7nALDzd/BBRjBNGU9nmFTCdazljo7I1fL3to96dQNwPNfmNdbYZu0zr+RlgiZ7ldkfpWApt6uNRyMtqSvR08YwlGXtJnPF/VYZXzvu8nR+9D32a33Ef0FbQQg/ulgRv1OgP131CrrGyzyIaupz7DWNfnVZJAJlmI37BULHcIhsKMEhwhnvxKmN1PO9XVQaKR8MQ7yW5hefgi69g4pxgOHzEpt0NKgRIlsWsu5wMMkaUAzac9I6Viyk9KnUNe4FoDj4sRVcd+5P9WYFbmSmlgsq0gYTYxDPCxqfSKlwELOSmGzOg4jdji1CUM7JAfr6vD6nJZ0Vw6PXwUh0hkzl/C9gCI5bF5wP1Db3fUfk1oUafi+Jhl09g9jLaSkY1skJrVxBQ3D5DAZcIZAT88My8VK0EeYAEnKlmtUyl7J//WBRTE4kRw/Yuczm1EftJqm7Rt49TaIdGqAW0rPIv2/NR6KpYvqGlhDOaqHSyn22FVvOnzSj0seaFGUWkHAR1mgxZ0+X2icyYM6GbkpvhbxPLWR1xwfo1KO1cesL3v56Xph6u1/jCC5+XnnwjWPf8r59zeemR4LVTebjawlGyD/b4ju225jDN5oTBUW7B/SGY5UtJ4hALLti7Het0AaulScC/zxYJEcRL9Yp49EvlGAHm4Y/qFN9OUBvKOHYLg30ue3yJ3zmqz32720mayhudBTP6SKsakWOoK3iwtL5GbyFe64KHFftjlC3h2Q3WboQh9828asuyGJ5zdlSZmLQLq5ZpdHqMv/X581REFPA4V99q89ssZu/x+xxnW+CjNxm4RD5sDI/TdBqOQ4bI/xQEv8DG9wPVJW1048+ARYqn/13CpJ4joeoeHg88eqwwvZwOoylXZ/fKNb/OP6CRv6/ABBj/iA+sosFEcB4SKKHSrpjMkf428Uw4e416ZWA801ELIU7wbHSVXjS0iRj/BOnXE5iFmE3okr7pDA61oz/WmiqK5H6jifYHnicVGb9kD/fbPN5F76m8n7XDYiajXe3/6TzJYlWFOeWPkRauMb8XsEXB2URjGDLF+Qcj0oF1HjHJLb40Yk8pj+yNn4gyM+6yKr/m299lePdYh9wIu18cv4P3k55V1UzuPR4PuHUEUQgv+8+rseRwlxK68apqDKUYlYXvxlNdrfRRWGgyetWCYTAoxB06pEIhvmQ8C7nsIW/9OFS393m542slEK3WP4GS0NEUAb6PY8ws3aZGvthBx+nvKgKG2eL2D49pLB4DIkcO0nm8hMQ6gf2CWUmjBKWTbcsE9g15dkiY2aqdlnXJqBS8ANuX+g2PmF6ryCuBB/2auBZ4kJoR3C8HJ5D7/NpiRjBvdk7p48qvk3oDQfxVN2W5Iktad4zCylmURRDJ0M57HsYsqMpXCCXttPnUfOsJvb0Y1iXkDd2guWjZq5sdBxzixW0+UFwSKoLMqwKQagf/YGFNZKWaG8yCOF4Jk4htMyrvosLadZdmSUdXLLdM1ElKUCWBihPg8ccvuLMrJKqlusFkGPLLr6nUgn8tEvWaQKX8aRaoI35vNQW7mlcmWS6vmcCqg4eAQGplArE1Kr5D8kyH/ViuraonUf4gu1VjzekOCW4UkqKceuRZ8UrBMAlxwdaCu3gGjH/3F25aKqeA/1GzbOy5xPmLSv+rwsDYJY9YjTXEcwxmAWqXAOiY/XQNDNjX1zfC5JJLzVWMJUBu1nMAA6WjrIJk9jKaXX6KtRcVu0+KMJ4Pj9LVNBUrZM5Q9O03scruAJBuO/7xtd0EiUt2ngPzXO025bb13HZktWMtJt6mauNpZ/3ZnL+bLDk60vwqiGAuah3bL8PdFNrtsf4yH0r1ghfpdlvanp92+8b6o68THLnuIo54UvHuWYyn5oiYLCk7NmBnPVgEnEdftUmkkH1Ypn5g02mbC9+O15n+/taCqEkymxF2Jc1Iygm6rocckhv8F1OGlPoE3L+YTPx1YXZ73cyDotyFxBKVS4Uhf7b++9PhaDqr35qk8Y3/ScqAUfFpmylWDbFEXFRNRy6oeKDFMU+R4tt2Vi+jqnqMcHwTBpOupoFmXHV2PEodSXjSuagDkkiY4vRJ+KIYlwoDixE7CpLqA/QwwLP/JECFM99QJrSdTfn/7wBYdUKhq7k9AxkPiqnQw4UBbKFTFvPRfSz1zVtg9hCnknGJJpyz86voRZs7Z5Ncl2zH4GhTX3uxssnfGEuKycpUUm7+eWHVeFB6c+icJc73HiyocZVzHgXPg97iU3TbC9v3EwoQNwGUq4ZiwDQyCcZdqT9g+3oWliemF2HOcKNlXJjQ155fsg2Mm/UyqFuQTbNYM4KxyMosRPsSc5suwQpyaI6G59fruuds2mG7bJPOH8m5ClFXhdu/hiDL6mYEnY6583tqaq6dXzhp8XeP7v9d2oGgUb/obQHWEblqnZNu1/+5XtFKH5gg04h8YOSZUZ/YdontNVAyTzguQifAsQKhodvWwlgzAqlxJBGYT56c+k7UthMJE5uoV+T10H4Ke5vzUQX+CjtEMKH/M5RRIok0hf6/N89GOJ4FkiaUnXHJnMA68j+8XUvQpOa5o13pkHwQuufbQtsCzelamHG+krFbJ4D5Z5x2ME59dZQ4wR10ZfegmHtGLvuWigQlJ4zRsuOcyhlCpJv9tyB7dU/j1mtavgP2MR/5KVMjoQSatXWHe6r0WoSJ25wRtI2k8H3JZqIHTbO2Z8OTtmBTAEoGABPjhlWwuY6QTvr9bmlSQkFV16+kNrXpFj4a0FTumDrdrJ/3r0nFGwTHiYGKKzY/cNTFt+Gz95C/uXWrd9O1DNm6lvx8v76YDKWF7qrmOXRAJRp+EozIxBDdnCFKlssk0lipcNK0Xf9gvvnlAHqxDACxpvxsjq16fitLK7v5rxQRa5GZ1i+G0UXq+ATKazL/itnKMdpOHSHud5/HhmVnPiULEQxHGBEKEKHZLBHEO1+qvgBvTsf8OnMndZ+HrxNoMEPP1qRQbOOM2rx96VUt4hACR+llkE8ewXwWKPROru+EWhJTWpLEMdhhWU6h3mkzv4nMK5xBqt4C118MhjZpESiXsTjqqdsT5D6POuu43cfYdboNdCviP+scm3b1O4RDwrT0i6i4/yL13aUpDb/xjtFF5XIJ9puGQ5dalVXtN8vBGpRQ0uuvhVNfqKmJV1tzYiboC2gVz/X7Zy0mvLUlzaAkpnnAbbEscf6QHS4j5P5NwxwC3UVaNsNfekcrkbyVDPiB1oKtyG79zlx+02xNNVwZlSF8heQAuqESdTcqFVdydLtr4PJurfu1CfpK56+WBnAoRplmRoWhZ7w+Kua+V4wLqVoe7YFH6IUNt8lpJlHSjLG8S5tzOMejv5QwMWyZCfpsQM5+Lq8sLLCdh9DBfdmmvNMj0/2VEYrdtuGtkSCVcuVT7u4mbmKJ/a+eKdPy+z9OoqGFXpWwEUxkBPu437dHmiiYR+FNEdcxPuUY2our0VESoJwSGbiKNm5HAeWWOC3XTlEyoJlJtX8+2PO47v22KEzX+RPuwqALE/XJMxhERTAOIfMmsArKTHaDWFAPoJVD5kvGMNW0aOZ4nxaLSX+zgItvHT8nBSB0vbOPN78ZZob+zAAz5bOrch4B1tA25GgukSFNymHWhVNziOgBKptwHl0VK965LS83R4h8WYnTOlpF+sB34/D29nse3B6epj5W8VRf4KpiOmf3GQXEf6zwNkhO3WIFpemCk0lejNduC5HcBtREfaAjoDzNFl4sAJNyhzlbF9qmaS7kSSFfJFTgMX73UKzust+KYNuGAsNdlRk3DcFZoDR3WZTM5tA6xQ4t2tdaQ5dbxxxMn1LXcNsnVUh6sBKH98ej2IxIt3HU8rqTF8Bs11rkC+JSZJVdiolB7otD9NzkxcRy5BH5r+c/+DJzccYcZIQ/fql3zeNuECtCXX6zfg06cfuD00/CutzHpZEjUvf9SVEbUgJCUsSnDyotA9T5MIwtxXBAzP0XT/jtuqn78o/tlVfOh60HqEuf85udtbF5cz/Yyl2zErYUReFmkIR3zjhn4grec/ImoaW6xY54GcsQKWD5R4Ynj2rlWvwjq2e5hjYaQB1Zd7Hg5b2LE/pwYhAEl3jQMmg+XHBwUaLLI4GLBIKDzxUXTNTL8zySpv5BrdbF0HllohnvjCTRftsPuwI4EPy/dG8WUByACqf+MCyCme/qLu4WRhWKI52hcgUsxw3+WrSGVOU6SzC6ttmEgzxZNOBBR+ovIF80tIIxS1sM6qxYz55QsDEHM/pHC5Ts0Y9ne9g4sdYufiaShOI0OM1zsQCxrwIXoXCdvn8j2nlPt4SqR3sIzlDs8hIPY0dD2GimqXmULJXhwN8/KPeyOdXA8LKLMpNZhouO6DjO2tJWh+ygiNoIPRGSoK+w09iSYHywZyx8A9HeNI+2Xa8mJpSTvXonRFgtWmMJTZeKYaQZMqCdO05WvzUzEAHTnzMzerVNuoUsvW/pSdkNcEa8txGmp+hZwFNHbqoLxmeldAmNiNTWIHEiqgWRvrFhXQnk1139clEAZ1SMaoXFWavNlb9qNvx/57mBmiIstUlK5KQ8ArpNOZ4Jt2n0FF5xytCzI3JybRA/25SSTG2MHQx1qmZAa71G/A+NwstXAgYC2z6CzDinb/89i6gf9ywC8VxIT24x/l2i27X76Tzr8kyIh8BSilOJgY0tjaT1vAj9KJ9YKliQ9XTVnDyQXwctMjpvklmcPbSpFh3OjIqiZg3mRQhVzP+sjPJY1G6p4MyMsq/Wo83n27or9zQcqcDSzjjqIL0uwX3+v0xoCJakZgEObB/3iw+zUJ+YHr64/W/H5d5VJvAyYRD61D2yYqVptzu+w/KwrM5XZfjbXzbl/VpCPuxMnzP3F23vCpG3hj9RsIfMEfeAAFZRoUmFbEaKQPMpKK0bKaJLnRhJxV/qtTfZSGTTG3AnSAmIs0asPTGnLxCJqGDBYuWoT5FSt74DWgTWXKBfReyVWOF+L9lb6b8fXsoXZ/fLWZNF+jr8frIgwMLqQoJm2vfJ9CPF2cONTXin2xWIIy4aONwWNgqeX6K9QYx6KzoFG832H/USKTPtcuvKY8d9vFNcWiuAwXhgX9eL0KsB/le+fAJsqCcssGyqsX6O8w6m15aksgaEmc9mI7uI3rmxHmLbdhccrp7g78yk+eXD6zj2wOQecTxLP5oSe3S8k3AeSsuVhZu3jmgti+GW3YTyYNxFixmGLmChrT7nOfSxVCHJVudWlP2rJohf0fr99rUFQLksyqGtjcK8RuoP7AFYswP3gaWRyqSA/bXAuZNZD9GKrbQSl/+AfcGAopd5aYtmbzvloxoHB8IztC1e9eb0n4tokedub6sdsY+mJkRPOQh32rftToBw2SfHUL4gX26bnkd/Wx8DSGGDFyKgOVAtwT6OPxtMfYTxQq/sFlGREXrBppLOpvA6mGat1f3sBODcvBL9gXxSLT5vVTLdlPxfZPem+vutVdSfvsterFMUa6kapnqgbEBjF6MZzyhv9Ju2WVCGkFzWVgXiaU2unfIC/oiCnbGZ/b6KGLVMBCyFTdkNaxmGs9vUS8JqTtexjVGSPrd8pglGXiwNXccHBrUIgPzLZoam5tcsAC1KqJ08rsXbRGQ87uULaRT0hUVD5e+QQUm4gKqWHu9yK6A6Pf4D9sIIMDAXQm3VD6RT6cnmz0QiBBJezc67ccIcL8bW/tAHHxzD/c4Uohtb2c2od0hGyVGHP2zLvT7JrzMy5tD6jaUr8P2V1vIpGKcyhOhCrNqt9CuWYGttIJOphrqrruz1wunYL1vKV9LncxJ/fMTw8df4HBJWqQq0dgfPGoDJ82KEcuZgsyR4SmwoadBH1braitFg+fihUdoLnNLx83uQ/eszoMhU3q/85QyZpoKoaU8j7rORb54w0cVRh6syVLZLNriwzXtpBN4MCmnixRhAUQxV1iqoMJ83mi/OwMH+yMWaobjDFBQQo+v6bd6R8TEOhw8KA4yNyOuN0gxdIr+jKF6nDBrJszB9UK1iUcjY6LbXgNyvDXrZnb0g30vt2bXnRzTWNjBzqesRvt9ZYlM/MLEq6ncgXLVf5/jXD9KQDa+ahrSpOWQWSGATGyfusN+0t25D65pUj1/U+Q+P8Y3KRLKL9TW39t9mX+cKZVxjkzQOxJckZw+/BlL/SBrh6h0dz8wVzuFJIqwpkjaSpxvnIA6yKFoAthQFjs98wSXpTwFQP/ZtU3cmDOGHIEa9PhiHHl6euG7I3iZLBV4jiwiGTgYL4y0f0cpVcEXIGWf7BZLu+IK0m/aJ1HaNt2iRXcrYi9vwL9WwUc6p7zTpW9G9DlVQhkKqM0HC96Pw0thNOXZ/1/e60tu/9VwVY/6SlQpnB5gl1nHfB0eTkEbq6LRTRQbPx0rJA28GzxJJAzbfu81awtmqjQ3xxC/fv1UmgM/wu8+1avBMHpYuLWNECg/M8VitMf3o8ML7I4R+vS6GzXRkSEztfDUtJnvQs3AzxdUoQy0oiUDJTB5z4Y89GpXGoamuJo5T2+beREWjHCVvpmzTAd0JW9AlHIXSpopl+Qvgs8usu+OeCOA0jN8u6mvCG5c1NDB48JIzhhKbMpjCELhDaBbkmqSkzk1wRotmGyxunxI2EXKnFkcTWRPn7KsiYJo2bkTNvYMkP93hh42099VmSV+0I06UVH4pz8V5VgDr1bV96dFKBrk6uv7ImXoZGx9Ip6FLW2k45PYCYEGr7nltYVZeQY4xwWHIyup+y+uZQaFXj5DOVEB/xUG0+blDpuht0wkfsQJmp62tilI1DXjWv5kBBfNizCnWzekwrAYBS1uWxMTdhCXKlyK9NSNDUjvIONmTTZ1GIVWTz1EpFmFDurlYCQaBpKJ1Thx4irfFWl9zjmvag58mnvffDA0SDZTFEzQ0WF9YW9zfCqAAlTotiagCmnsqWwn5+mMT5osecrl4KnYZEX+bTzapwVYwJdYcp3JmysQzCOcHDAejb5ICLEOTP8xF5j2cDegC/SDXcwmCy/ZoAIF73U47/M3fG8x3iWyckyv6h2JYZbU1gkvHzvSZvIJeIfWusuM04ihzPwgyZ9i7JDeSrY8ivwo9Dl1+w283xaUZJU4RzGgbm7DDfLa5OhVPxp3G0NVk1uzFlDPOyibMawpIFgUCN085jDHuT79Ir1EcD2Ll3mgiQK4JML737kvr4FBFfMMtJyN+eWE56I4Y9m641Vqe2axt7rUXUukxQv5LTLf/bvmJq/U/68hLCSAbQw1+jgcdoteeFnkSfEFGC+d/1g8B+PYLPLYSDZsW9/PxWxsTiyZ4JrT5+oEsa0Sq423CT+HIFgKLh9MROIPAKS4zNC4mbmDhQbcE0xhw71vob2XXbgzDO1ybmIo0m/IOpb8rxZG8yamcDvFH4cR3RsbJSbs6vGf2+2ZnrqPjCj37ikj5y4PWZ3CPL8/Kf4Mdf5aA+EizxZM5pG+PNekATrPZW87tMYq1k/rIR2Tc/CbIcTiI4b1/Xnyk+0gptmgbxrvOjcRibps3jOmNvyl6FCmFfyHMeeHDaBYS4N3wa6bNnMxuoMnTz+Bzc5wo3341VIAMtGh1uTD7SvN7ZAqLa+CPB/utaUGeMscGqjfLsghi1TmMsi+qG2KEQPAHx8i89ZvsUHeKgWLgjq05dPwtgkF5hfd2sapGzuF7ZvpKvCiuq0k4vZSjOKVeL9AIP66SiEDHzYl153Vg/suveLGbS8XkeT+BYM8nM+4Kj9yqoWCbjGGAJbBxCCP40WVVzNyUyvtObF18GcKVcuRXxocLI5T/vfB9WI44BC3iFKptvt3BXJlOQYZidIyOT5KB3BmhY/tW24LEN+JkqVaDwtghql3HgnOEWD3yNX6U1ATYqWIEIbmMNH1xDKcRa15qMqyvRI04fWuLqIyFl30Yaqfp+hmng90baAJp8RvhE5H1mU3Sj7An2kl9/+Mb5fZzjEO3PDpSl4GsV5Rm9iZQe8gAvpdD+ko9TwOjjolpuolrjKU86qULZsmSq937NHrRxcM15A7ueq21bKPJtwMik1f6C6zxOBRcuHmE2J5MnnVDxi5RdXFRk2RLIxRO3/lP1nJsaAqzSNFVi2e9gh3MvgbOFUqWYNwQyqhseUr3sOpff5LiIKivP43KmmkVQxY1KtxBJa+12woB1dTzVT3zhcnRM+mm/Brre3a3lfxwWRso0A5purjPppX9MRYGe5OQgul/1EPkr7ma1cT+myPiWWfm9bkQspXZHjlmfh6f83vIRGavZda8CqW7PYK7o9+huWORmUEQTv3YbXdqAbUzpa5qGNqyXsSfoRN3xqBPvqClXxIamN1X8L4C/TXtOmB+k4UaHyyOmJ58Z73uwmVIyHlQznkYU+bst0Pt1ltPA0YEhPXXTBGYnRB46fZZqZRhm4V+pX0f7WEggcAYy3Gu/7CZKEtVIuXjZ367pQXU9oyLeUNcaIhcF+oRABFqqZuEAijMbaN8xVuJiUI3S2h/Z0BCZc8Zm8Yo3IB1liBj8w5QUVuwpBtack3jHdqiyu/J71Zo6nC1jzBEP34SoaKQbP4zpnZWeLKWEjzSkSLYubZnWAO5Om9XJSjXaBqgNIoygj++QFdGbl7QJ4j/Ba7FLcwzl0ikmAT9DknBxVoF5q/sicK5HszX/OXhZX8CCnLQVC/NBAty9zT5ARyccoEiRZCEOLpIcQrqdaQxL8DVccJY73VjC19gNG0QdcwvHjaNi6EpxmPEILyiKLgwU2Zfa263PDRDKaIBz9u0bXbOJWd8NGoHEGPgJV3mcKq3ik9hV71F/UL/qtFUZFQjSgx3MczX3OKoxfR7VcpUMyQ1LsnQGQ0WD6nD/RId3peka5iS+/GCZVljlnvXoNk482Lp176PjbJP5K/ySv43zqsdsGTmIq0z3PtMiU6DfRCLFrfR7SxpG+YDItmlRk6TuSv5Qj3cLFk/GHxA6XvzS36uEvxYVr1w8EKQXymCCfzovQH/e5+HG4zPLiEi5DaTN893LriM1xrAopo1AFmOyrovHQfqiYvT6er/LlbWRBZpM/DbKEGCE8PN2wPe4PLcfsRElHaoh+WthA9LrCoYVy4zlITQpsPDk/4KhWi4E7lJXI+3wZI6Bam9/G+ThppB/6SqJRwAB8C0KKa/x2JDC5unPTSPqKXrJy7BE2QGTExk0dqum8xoa6xmXuQc5yxaNlHmFAj1dSe8nH8x+Z5psWPtTctbvlc2C5M98O98vFRIPUiCWhaSStpVXvi5cbfeNkLRxQUczAg29QoXkMXR7bR7fTLZJwR6XKkUngEN3chuhrdKmOcjidsXduxW76ZiHlC5m4KCiCVuNMnK/TzgkKR/LIOHnOwuJCVQ/mXG8hwgYK43lpstyj5F0lpLPAvdmlhDHsjrJFblJ4Y0g0noKpF5wHMlJJCb9Bd1BBI0zKFmA6+iGYqG2sjL157HloUTU0VzLI4b3o6Sxo9XeePfB0n8jrESTNHNQ+GoJZI0khpxN+lMaZAuwGDHMmLmX75DeZ5YEaiEecFdtEd/fxX0aSdtw9s/57gaCg+hu4HSiJpuePXJD0te33Lzux9ZkxkHeYy+XkYOC23dyESLEdZk9xQamPyDXEyHA+WUH/ZMS/x8ZaCa7G9hIuRoubXrjbNtK0Sk9sR5wpJdCgMGwUXuK1fQQMKvkQQzce1VS3wtddV26VRaDK8R22x7LDVDJo0k/PQr378EHtGglP8tGpHqnqwXSupKJmFhz3M1fnkGxYQUhST6lKUytfWoZ4WqGffQpcpQl8svHVuSFLHu1LebQ2EgMrZ1DWWrYjZn7PoeGjpINeriHz+Au+W1Ty2uhxkFAI5NCsUfpPCfptSUNmdhh21p3PrKNBL23W0Zou6/47ZjHqv54R3clpaz4Gs9YnKwlLQ1k4O0b17KdrMUiGiRhoavuQM+lQZazdYSoLa2iUbhIYhjaqFSiFQEFVf1JwupzsoqTYWny4BxV/nUF+uW4OAr+C2Vv0tWr6GaDbhuPjioX/kJ8kHI75DuXJFNV6PXTw4apbs7V3wCdigmQ4NMLufgzyJ3Qvz/2eMkG2UI+sr8WwJNrinGV0jsp8H6kFLv0gxmwN3GdQLJUNhs+StTUgVx8T+MUNz2yvSKKgh4WEnLwQGrFNC2ybNNEDtqQ2aWarUDkPa0mkPhkY0diJ/hWhp+HdhWbWXH5ofLRJh4D5490/y0GIMKnZGWeEZSptWrrZsZRjfZQaSx7iM9XvDIvPHg0QpkFuDC3UIa56dKUWObxZR6E8cjhxDt0ZkdUadB9j/+HdqIPM7ry6T3IcHCBjIgl0GtLQ2CYP/bePTNwt7j2wZGDpojtcD4C+kNMUToeU86KVFKlBz1Kx4zgLFzhxG/DsKU3V2bp1M9LClXapnyq44XcZyClZtngbG5hyvbw4JUMOjQal3NkRz9UEqTi3xCHF7RkLPQr4NNfMdKYgFuuWToiNQKsnPIG51nLVt4wTSPtYj+RK6vgvTDiNi6wwlVhcqtbp47BPa55mJ5p6b2BALPM45YwHwZaz79yq1bouXg8ESuEa+SKXM5UAvGW+Jiiv6BCezltnQcgd03PPvZmps5Z7SHwLlUnmpZZmYxUGRmXVrhNiadALVxdpFyKGZtcHBI03Y/2lBwR5DODKmI4u9FzVjExxOagzQ3W4KhcIQuTF26W5lRjCj80aggi1hdUllNtA3HXd4SWyL8ydrb7dkBE6j3v0EFulaOrJ8FfSuRjVVGpx4d7mOI8TVBxWiVdZsnn8ifnElTvor4EAK3pSGFmlBAV6wxE4YDOSKXVLwis4omur2Z6Ac6bH3EuYVp4wrWoG8ORyp9ytAzWD53MbCIPE9qjoeSTGzxamxzNjkapbHsQwK9xRdIjT95oM1NGiTsCtsz8HlAisMKFkh+HOMfza6u2e8tmVaoOwNcD3rgtwP/t/YyTt1kzE38XD+T73jMXb1YnX3PW0eDC5XoS1bBZ0IqkrrBS74d6iURKRVuVN06LjyFWsL76lcSHTae7UJm5XlsEnhnkyBbodlXj3Mi4Q/ESrAtAb2QXphMzdyE1w4geSilGFccK4Z1tei6fV10egvFjCAFtmmrLqny/8frRWLzYJovumK4B/4D2YXE00ZQg8TxIhqIPGBzlZ7RApOTfgjozYBKpPSBaCQqp2r+cr0v3pjEW28pniBRidX2wg51vaRZGLs1fteApnMgkCI10WpCKXXi41mzEOVCG8TAcjMQ0J8Hzwj1oFesbFIZuRd/z2l7vvGNHJ8GeAkkkyR/hXSbMLULLFZuvBkeelGd33Ixr650p+0H2KF+XtvmMK/qnnsCDX8NDjxL8i7oGAeIrx9wKGkceheGCMEGO23tda8HPVrSjiXzliHXcrKHto6qeIPH066b4czepVNpHXMugwzLyhMh9snKIQQxy3FtfsWJgje/LZGRDlFJIOP0ou3BDESWx0mLQaQ65xf4O2D7YrywsHhIvN2HRvyZc9Kiu+Bn59GH4hg9WipC9rWcGOzkKX3mAv5Z0aFc7HCLYQYsTSj4vtIVW0zo5mJJVP7fCqSzw8sIqnN0IW7DrcpdL9XRbms8AIdf6qGnC5nDP7D9RFcxzo0Y3Aaiezd/rpFgn4Jn8QHtuRjFZjluMbBgh6d4Y3m0yTiaf3Ydim6rUi/Gqo+bLMPNW7qdda5lnmhfiUM/f2laEG1SkLAVK3tN7Wcp4L36txibh8V+5sxIA/QdtI4pZxZ5HBiQMmjddvEzSNRw1kKo/tHHrGhYYKbBar00C50upBBK7dRhpM5dHo4HgFUpNBG2PJAFVotHWjuMiC0gEh0sUYvbN5nkUQQ0kgVq6JwXVaH0WxSEPgXKJKXz+Q2uN1HcJnoUQnsPKMNSV5BPL2KuHKrVCw6h2YBJ6d9Zlt2sIWC+8ubliH7pddbaODsWFmO8nWAME0ws6qjXLd1sFXVipZHk+Nkhwu3FGUeAysfLHkyItfXByY4XTzPwB/x5QlrwsJuNDHtgvk0H62DBtupjczDoWgNW6diAnrn306cfibJAtH++dfGGKMyNDJzQXeAmKTHrkzKrKQIYsPjnlSw+LHvsfTGeWdPb8DnmT82EBx8f5zcmykelCqKK4doxsWSVO6q9xQImoBq+Fie1pTy82rYbR7wTmkSIPvJo6N5FlzT7MuGIYFJPOKaxEytEe3O+bABq/SV3TL+okt4njehdpdsBDyh1fRlcRzPlpXNNeT9KE+UsorMr9bb/rWXliyj4x6NjeYl9n2cYfP2ueisvIfBZdIJHjmsy2rfjzsc/1yMWGJFnI1W7wGBthKan9CbNyR5AJG4QVwuka+ltIgbTGXm80fir5sotsyRv1cDAWos4Wc0mtcZKUblUTsTR1PTREeL7G9EERqkoC4D9PGGwdqYl3nQoSgzNt203NPUEJsbuemg/jcfqGorE0RoXObxOnYI0nDpT3FfrW4fpEYpvEM+NJktvZS1IKIZKxeQH3dLFjejYq9L3eR2pNS5Ca2ZqvoQieWtU3kAN3gaVgveNDzqBqv0KvuWIyCCIaJiAT0AHqcxR9jSzEPJUNKGneJhIEscG7TPLBVEa4nZ/naIEhscsASOihWLo1imOTedQvshyhQQXRKwonBu4usj0UeKXJX5wZJD3Tak/IQgNCTk9NLSKRVfIbIPQTD4RH+G3r2Ig6JGkNdWL9cXkd1inEGn/BNTS3xWELuL6PR5e0TzQEiJOA6XxWoeDpQpTMZRJCjri43MDPPOAmx7FU+waLF/kBvbm4TgBKxO06+t8KwxERaNkkJ3Q+BEHh2l/n5nai7Rxx2s+mqvkLwTsiOIN+jmqfy2F9U/fRJmMu+OnVL7j6EL05GKotWV3Xelx2zec//W+A1tFxb4jX4JKjVAING9dLibT67KDxoDnC4bLvdjEzw3wUnOw89Wgzmn5Rxu7Zb49Xm0IeQPikjUO9yX+lRrvwj5X6FfSEZhIX5CxyrfWSn2SkxVfI/LAYRdxgQc5YQR0siwpEpOXgS3XO4hk9H9PG7YXRk9tOp/VPMf328LkPIftwrfsPTD8O7QZ++SGktS0L4LmWqE3MKlHm/2Q0hjyuLMEvcdKDDpv2xqfiZ7t8uyRCI0a4SK9map0/TDYfWJKSxAZsWgL8dUB9jwcXj7TKhsq1q4r/NSdfvWbugARSJbmNo2sY7Q/lsyZ715l9on9h8ip18VoOq2IEiaxwJAW1qUkKCLOcmWA/NTJJl2v5IuCl4HP0I77Wya3Q3Xv3ihmud4rgkMo+KDBiBG5VuBVYPw77auxd5XZRXAonXchirdVwMRQrKwJXKjiGwlMd9eZyrehJgRKYLS78lZ3ZDUzYGm8hRyFpYRHDffKUF5rm+5Z2Eq/dP2+f+thcVNaQG5I68sWBCnxHaY50uaXTM8FZbau5/vjCTI+F8p5b/d33JusoUKLqZrzNZsahI/gTje+dmP+vCDLQ9QklaC3dGwhMnk8s618Wgr8H6Rv8A3+PoY5VmreHhwvc5qh0lxZitFLab56y44GlcKCOTmoHPjVbuFo1//FeQNJmoDGRMcXeux13hiL7iVOkXcK4Nb76E7dbMBlK4L3FJ3rIUoWbLxNbg6q+t1P4ymsEF430q9QEh9w9Nw+CGshx3A2AySTI7Drcqrxb19QXlBCgnbDCI4iWAOLdRkXEifAYiaLyL5qfQS0jP5lcVeOqsNpnNQy6a6EYk5yToUBJnOuMlCN/6DYO2SiRNTwZ3bcYUgQbQEJzZXM002BtlMjPV0XxDhGQrmviP2fkdcrJQWeffX2nr/4IcZGYz+EtRFphQ3609WihoM+8QsCL9NYD5zkUBcmnV71l6qyuptvTFP7HdjP+yMtrtYZxZ93rxv1fnkSGoTlE0tRux0xdf+THUYrCLMZtgsmhAkJ9Ry37yunIQb9fQ0cLecnTeWvfhJwDf6g/65Be4rbHUGvjEbQiqMyMSFPut//LLxJOM7gp0P6BGotfKojt98GzAY5rxwWwrdoOM7facJG12dw38uVhsgHSlufx+9Xy+00Oz0/tFJmHSoBP+QI784GUrX2tB3fCvxWlY/qhHjB/TvNtbZ9kyN+1LsU/EMlO3/1ab35W5YCKVT/7qSctq0Q5rKfEH48bvvP0Bbbs+XsxlfEEFDflDLCDKpZe4t9zNJAkFcYqjxUvtr2TT5gcFPtnQ/SIYAO4ufXViYqN2vO3V5z5hYmwSBl1MRqDA3YpiBt7iAZbGRMMX7OZXasTYo2cLX/VQMWWEmUgonDPdv7WHued0Xj88cI4heLPy8pkPkfkepjtc/YtR3ejUb9ekmXjPWjxqbV3YNaOnIo6qh5eVmYnPvwBHPKunM+uCINKcBavbIYL3sQHoEtmxG9hIIJ1Qa/5nIF2z80JcomhQnmQfSsRk4MkwY6AIRXw/Q1sws7jagGKHR11iRJzHLzPkLWnEVhLtVD+a/dc79CsBS22xSl90USRQoES3fVgShXeU8mJmXTXXuKcyhCorGRvwYL/2Htgk6juxICdQg1k7eFdQc/SSVdInfDmeNbA8zNw1MqyQ5TGSHZ5k08MjC0jmXOKgddYlCFjjorbGmZ2hBBjTavvZpN5ElROxXYkt1B4tW2UPfYgQwiMWMh0jxAqQF8VF3KjN8u560gnklF8ufEQfi+YeZZWiM5GEqjQMXfpv2q1M3m/2PgsmZX0+e7goYfeMa4YXPT3rL5jv2keKZQZSh9rU4V6zOfQCaJH23lqb+De8vM9F8vNN3xWYZSlgpnQWv3e/mhug24dfP9ON/ZZ+lAcmsZqF0dzLBoqioDHMso4t5MXRHHs80l4NoDAVP+Pti3YABZYs7fIBQf0WrREIKkM9jZYjDjygZ/hWC9UE2Q4gM9cucfDf4T4SKO8lwRcxY74v+iq/ht6/v3jFIpPbjWEsMnG2qOdLLeHlLcVeFnkcLOxnD0dUzwvWd7PLx8ICsyuJ+hytRF9wrjk1u+mK0M7afj++C7RVbevEcjBX1r/zvdTIv5xh79uwFdPBYokTfLtpk1ppNX4AqwPt+G7TcabqYbdUwONMYwqTTx4APNNH5zW1SrR5xrCvLs49st2/JUodAPdl1FHH8YAcLYIb63HJBDrYu8mWHV8YsAyDbmoDyxi4MlhGAXBR87wyOg5DVBbQmdd9zRT/1MV06C6lVZiRdz8pk3jItDFp3A19urlm5s0pKufWl3/qtVWVyM7v4wA5vsL4ZANnKhgk/K2GUE+6AyLBnmKK22nDin5rlhQ7eoLgT2kipUM7lzWCkg1MrY8GUJMVzet8NFBr6NzUyKXf/m2/WgeKf7HSWRHm2lqdvxfiXk7ItVxQu1EnDpYqb79f5cL2VCtk0wSZAtQgSemwEZ9QjIZgjucEd5/CNlATPL27TrUjWn6TLZksbkJtVZOYmAWdD0XOl+qZtLJKsPXxiiGtarJmnGf9CK8OPt502+dbsE0OyzZz68nlg+FYhcMcl8nfeMiuTlF4/XYj8VY3WkDW0FoXHa1uWDsG/hejJ15fl9K8kOuSB66k6ji7oM2ahd2sn3GNKgB61eI4iLM9ORVYwzGLTig9Ryb2TmNoxQR47AdeJXAHXhw0mT3rX2yaRFn73bzQcRYKBTl1yEBe4F+cc1ZZN2C0axEO1wkfNPfD+FyrxptvgeZd4s6waLonu21wUCWMumuFP9EsixevVLwZWx23Nstw7usC0kDuMNVSrCqHniFQx2ualjrB4Raq+5VHLzPn2/BCmzjrGXxWJGkqJ68gLFcHp1v/Yr9RkOdF9CuLWX9Um72uJQ9WCcr433DThlcm5YygXxSmrwCxRfXp44AMxeo1DlCSJlg9eZeBE+qJQdH0c8pMhPTebkW8ji0Ni2N4eLu77m/P6+A+yD7ysN+l+B8DdzZrqo2WW/0Lk2B4x908TEpezbwBFghxcMMwTaXutMCYDOL3/5OsCaW1Wk0xF+k6oj1M/bqrvM5Kb846tC7qY2R9qp4mFmD0GSWXw9RJbrYBN8vW/bvwiIxCnKW0TKZorvfoJIQ7H0O2uQQmvy0eIq6Yf9DmR87DdTZKJRscjsxCm90d3s3SUrrRaAzzvWX6FH+Z2A7Wd+YKeW/fVHd/J6SwOQIDoUPG7YyYovST0O5NF/tF0O004+i+e//hV+q4u3xdnTHH4IikxJAbMtjAoFMnJ1t/8/KS+8tfpWz74R0hW23sb3Gp3FnkSk6JGxbuCZCVaSqyDrzEq33EENG4Mrs/UFWVdm5/ajxeRhjnLYNTO+7OYuSF6m3Rbp47GojqCdBVTxNk+bRVf4mCfbnn6Icq7pzV8UN1MFhf8qdSRUxZk7bFsCwnFrdXC+Ssk+jfCg1VhzMC7xMf0G8tdLf/r/N73iV0tWvm1E8U13RQZaRkx1kgmJKNSHQIJfb7ZfqYOBBvTk1FOBVI3BKiciLN1Ex2EcuoNYuikTqoEMLwKR0jMk/e5L3N2d0zUvlmkhOqR2MwvbWxOdHTOWJh/SmrUZyp2kEF4DoTTV52FkPPslogqR2g7LOkwHzjOteT86OND3J23bQF3EnsK6WyrXwmwBBBGy8e8+YHBeNJFvmnetkWDLOGbApcvlsPL4X3uU7TFuRNeh0PBlrCdpCZojCkYLEGPnls8nSkrJwBc36gydx7rs9bwCNO9wQWBUsILKUSFeyOGWlx0A6JBM0Gaca6YBp1WtC4raVNRXhYAlFRFiDAH0S0ZmiWRkcVcaCiapZAm7KwDMevmqKgMAGolQnApirm1sPtAqUIWuYNppK8I6ByIcpjgUVnmc1uVXsDi10Lo+VlPyFGUtNdIvrpyzW1VK5iy/xUX3kHzjurzK0if3O7AoW73i/gvQZLEC7vWa6tDuwN3kaXINNJhsVoQmzbtESOHXGR+pOQ6kYEixXMbLDX/9HK2riSMzgrcYB+0zSIKbPdO+wDEficWNMlrsfYKTkLrSrgQPG7/qdTZUU3SHy4/ZFRx/4HOcKQX2H/Oq2e5P8x/MYcssTe5S1f/mzvBcov9TNAfYs2/273FgXh6d4M0eCcZI8DaIUTrloJp7EQBXzeTv2ef7/Vf9C9N8ja1uHAHOicp+3QpwBVGt10RHcAHu1sQCCAXDDjjBfjVorLrtUE2O/tKDtGVrkYArAE7NguQS3qsH+Us0tDAufafOcK3BgUaFZisAsPvXxcEAMAeml+eRMOvWNb3mPPPwq2stKNydmOmnrhgHVHLUvFa7rfl2yO0RYqUQv1vajmv1fTE9ySiMrxRka//cpcQZQCxO6mtHuvvqVnYGQyFoeOPT9v1RMXA7ANMcL7UPqvDVOPyTvSXlPNXPZgoOEEDtbswDY7DTiFjHHi/C77X8Iuc2ptjT9DpWu+jqfG9KaCmc9b531OBFEHsBtSqMDo5t6Gz52RLAmOHE2v/ovVbD1YRVSx153qd4a3skhvfhhXP4Ra3AroITugsXPJ43QxcnGX6rCjjUUBGFoqjN1benomVvz/2eYbAqbQTD8BkgfK1EoGsHbHCI0Bm2zGHp2JOmz9Y3Vncw2W46HgcuKj5ED/3yd7uGcP4ab/FVC8vtwkz/QsWADCMCQNb4X7mIGP1FfDadAGyL9inz1p2IsTyVncF+/O7h8v7AsKj+8jslBpGk+kVWzHoV/Gl6j6Mt3lGGjw39NQbxxlpW3gALic/KemEH8M/wvadGFxd13VlkXz291s8Z37FMCJS/3czVapoge1XW3soYmPt1PLt/lh1KyQp7Vl3MAwdSSI4ED3ZEBIwa70BeUsx64jumD9i04g2o/Ez+0/a1gQgRR4DfxLY7/ncQqyLYvwK1lFa6SbLiN8ldugPvEgqhB93Baap3pWXcDNQtUQNalico8iEWCE3q/uHFUMrYOTKS1xQIIcEuVxwB92KfS6q7ewAkv2WAD48ZEIiAt9FUlex2sqqDuQUk9JefyxXkWAWdPSLNr0vI5RMZrJOWR4nvEPchr8k/O/iblSzxb2KO5JubkBs9ubAx+1MBkDwQ43w7bj9NBN+N0MO6s059l1ZvwqkO8yFC/b6VSU0se64qAs0FLLMo0Y8k5ocbIs28LP/rkhaQyIzgJx7CLABBlgkeOEEDEOCbw9R3HYo22DXvc4U67Vl0dXpzmLe0r0JEi1rqA4567JEtSEsozxaIvieGp889jV+Uo/PQdOxQ+ENIYGA6RibT/UmxdAG2rp3Xk82ensLdWoSp9DXT18XU84wThKnyr3Y2ROoh3zUBmRUo24cyKixh6Kne1a3oq0XRU+iVaaN8muazAxcPpUM26OX7N+8vZoj1gEnx6IqOhZDQFLvvTsHe4OkqdZCJAdUBkc+mRQHUVcTVKPrlbDSg4dNixkOQEU/jF8c3EO3yoKeNQW8uAMRCV0LXh2BVoV8tIyIb27mCi73hXell+gwRkuMa3RUvbaF7ucO0J77CP0eSv7tCPQ7CnGHDwBMkGICfc3CPHE9u0QIuf2v+ueSOTdJlLsPEzlk8mmsSLrf2iJREDkedQ+Tl/MyOFjrmawFyNQGolFpGylwvgwV1kxeBrAfS609OIwKrbswOsfC5kKsp1ILsglfyqRhdEiGegEHR54DMzk1V93+/rLRgz/MD9dD0oV9WwgCfaB7hasFOEi545IEdw1lnT1bXS7b+hW/1MUiK2LISTk7dgGoIc2JK80xfj2O58haZIKhG903FrTzckb0EhBlwo8odK1KEO5lhNZqimsDxs/ChmXN+H8AIwLarOLkYE/f1T7vin/QxBwOemFQvaaDGhRJG+aZ6u2E5rTF2GFTOMm17TFs4hMBAApr2dFHL8vAH+DYXCPQd6oVdGTSa2OUYMa390Gz5jlajDPaXKV4xijHIhSBRAiEIuB0LcWk3NYUG3gyeZkgDNmuShNIIDfqjZlwHvaB3HqJLTFDmHNg8DOzaf5i2bUZVfVTIrGuX6r9f4tzXxOUFw8a4sM5NKYbZi9JHMLDdGz47UbIfB4Ce4Ks8xeyibfB+nKAdT1pWWgTrpC1Etjiufs8DNw8U65/VpXHeNdOprVA+6UTVgzwj6ZBeHhr8/F5mk2GMiIBd0F0gGoWFBOuIvjeCMPnPLMBVA1FQANYQlJZDO8iyIyhHWBLgxPNsO2Wm6dRbpcGUySYpBDSOVaPx9YP5egYKU6EO8ZIrUkamibcOkMv1NmQ7r5HI2qfN8TNhZnLdCFUxMEicVi2CgcDnKW67b5fkTxn0wpQgcP+uWMY6B7uSnI5XUmOjiyOd53DBHIeEmllM2apcp5JDOTfMjzH5y3o2cDqSetPVud98GeSY7mcVJvgt0be4Hi+FJ0VFDRuR0ylrBS0o+3IynxiQNLLV6ggEwyke95WQe0pQrxM7Y0Zky5j/v6csrP3/2I8szYPxLNKtKSboAcTMGcC88hNM7ZZkSIAjR2/af1vjGpWPW7XUaX8RJivpXxsVPqSYwIfGnGw5CbTpsCVBIivLJr4TzkAanYowV1vgHyEmJHmfnRy67muH4JYEcGgn3uN4CBRy/EweOFU+NtO9BFbyw6uZdzQAbMT3kzfvUXYAdGZSrHuA4tN1u5Jxp23zXwTZ1WvJa3ZYRwqrVpkH2NvCckDlO5pWe96WP9cYoBkAt+CrF73rGE3uk08I8cafSN8ELHMfehfR0v0ZMvaskNIomIJeFxez9J5f1gv0j9p9NU6g0UT6qP/bfR6z+kW9exRrymqGoDd0lsoH38phKPF44NW497DIxbfbTEJYEVwlRdUN07PZIvQRELZVopfBiUYNvb99CrNJVVPERNYfpqsU7NrmHbI8HbawL9DI1o0c69KZQlDPOcYbhp9WuKZTWVLMmxJq4q5nW+pHLdFqIkOWtqU37WUUAdlf0EIylLfWd2XZTWUlUitORnmGigh/CILV9g9nKMZwTwyz0HB++t5/x4Dqf8RL1Hr8KNOGtMSDd+Z/N8SwgV/6Ucp47Pd1i+W6D0WtLWoFHbSS7KqI9xiGJ/C1+ia52hZ+63v+vqWFdCyIe6jmbZgBaoz5roHNjxb6sDvMu1rc+6tCm+dx84krPGlP71KkO/xFnCkkeLwPMYLRXmTJmriXe15AxhlGKsZRTx2fp8w5wyhqjypnouYwgIDEeBPmGbrp+augb4k4kcKKCVD0zw9/AEZVhHf1TD+xyDgXsv+yWxUgujrdi0kkzFf0F1xOjCCM/ZX+JQX6XHeY98DybfZQWLTdp5SNHTYS66f87n4c66dDT48NgZ2OTBp/8NMXhSCV2vhbr2w5ALyVJbCw7eCWd1Krd5t3pLJ6gqn+hGUWRGulYYYHAHWMOF0Vq5Ez3KiiDj3hoh/2GhcMzsXu2KVwZP6dmuHrJoYBJLbVgWZH5ZPf/zjYPLqPf5HYio97CgxxEqC9r58aLJUnqFsLrXzdtFcUqZXNrQr4CAx0jtR5ZSW3n9lu+lEjtV4A/qCxFarhkY5Jd1DLxjOMnxdZ7/D1c8mv+jbwtYvfAX5GE1nU72Vf0G/JMolEz/PNI0UqqKx88HK9eebNDzSQ0l6VcZgbKTCeFaBH3jQ/XG3I3fLJyKWERCbt/saZp9KLz+R5L7mJVuxBEB+3I08DsOIqGezH6eUsSy+0to98wjtLw9wXAd3nut9/CBdHoCawxD2miC3nbK5dlb8TV9RzCWyihKkLoqcFKshRkX0Ch3Q6S8P/jmbM12MGX2+Ul3Wbgk8Hj79BBawbHlpAGjxngyb6RYfZKn373LB3OF9BNOD4HCTxQr+338m+IyO87YJB51Gucg8fJflRbcUVrOT4ryxK2uXdJTp6LtEbhCk+UyoBs4xmRZbzK0qS6A9NEXrChRgO+fG2xf4vobZj7WXH232hBvtoo+TUnwazj28A1CFsUvbcmv5dt+zURpYBfuwtSfEaR9gqt0gnfqA3k06teaLlIM82sf11Qy6aKQrziG4sWgWPTACHSBVoPMT1jDirINTn1MfpJ4/NyxHCJvSFkuNUkr5A5l0mPonGyYR6qnOB+G+y64AxmcT26uvN7Jipa3KpO3rJuER8c4tjDa734Mm+qFhPhlqmMmPon7l5guamsFkq+esMFAR+3IzeF/XZCC9gHhSc0g0pqF8zPV5tK9xqh6C2pcSO8Gxxj+v37KnXTv+dkzKjg0SybsVS7aBAv/ZMJjgUSNtoqxk4ZInMpZp7DLPToWkvS8IZxgMI71AUITVDHfY6IslcN6Chv1YHdnO0e630qT5Z2EtuGFf21WysDWXBtZSpVW0l9X6IRKQ6no+LLMtphJzvvhuQGozp5a5YEDTaP2w6EqAaou478TxCgJL48uCzKLIyyE/vbr75oDu6LFw/3AIvLEjk9c5Ykas8a81v0K4kRSiDUlX5szSp9BbmbwRvYBJZOjG/P68JGhum0F3pH5dkWYnNK0M8ulAM/1cAcykLbvllLITsbjIjf0JqBREzJVb2DTWu/w0jAETYOXveouaeN6T3ujrj9yWiqEdabIRbOSqtxVf7EAMBXtf35y1bnFWgsbY76Dz3E5llxeBLHMpbTZeeBaLNLGCd1IkT+cq1efVZeNFIJ3jtCsFebA24LZcky3HGLrP6j/YHAw/VxDnRlIrUzAD9vUOO3eRvdeYPGkik1Jc2obZ7/wHi8fATgqvsvQZltUHiMgbN993OO71/UhYk/6IDmkd1RbbVC4xstlHwPRD9ayy2X6ozmJ0/8xjg0uTqXCDUWkTQP+X3vt59EvOpI55BDp2q74HJyuo9dpE84coDPh9UjHiAcz981eE3WkqCX8EKQr2m9YcHb69VChf0T+Q9B4ppvNhpV10nrdga3VGZa11h7AXHv7cpT4mQkMjPgZE7OQQuc3X5uaShhyYBNznrkILh2ZChCUKMmho7IbWmVaiS4sO+Mxxlh19x8iJ1T+X88GZVWLbng0O4wKyVDoDF7dSncAK4mR73Ly/9FLWem0KqyARm+NbPLQnTepsslze2vixWmbLB+v+FfH7ZQkqT7tnMVV0olt/wQ58OjlAKJSjW8RV/KCW68UyJdTAxbChmCc0U9xq0Hx7NXLtk6re544Qbsz45ck3nybOF4FMAlA66L7Oog11ykxeGTqgKWsIaoGkHuh+Ze+KzU9ILS8SLzzr5LgQSPWtEwBqqvElWJY7ADWLaV2JRaJODSndixyGBzv9QiWgOZZaSb7V1vKkJd/h0vEUllNai5cIDkG+fLmqk5+GmZD4nlCKoUI+ynrCBljRK7kCaclUA4mUuAcaaN3JXjPM5Vsat7pcwnwGbPO7yay1WZm/qWMNcWtERNC4g8bC3dEpTCNavmOvqNL2symcwWBEecNiZejaYBF9yNSxFht6MzC5/LOhmf1Kv0M562O+xC5WEdL2yE5bjoEdRNYuIDdDlz2GzB5ZGELf5nFpkAurhh273arATn6Y2f2Jal9Kkn/XjWOittkmD2UZg7mAb6QYEiatZFieWaDW/ldVtUqud/R8V/BBAH2Ai9BT0tXiosuDQ2u/kCPqwInfZg+ugz6qocX037ucV5cZHixJdtWO0xBHcj2rxPqum7U1b/kFnds8vjlZTdjwKyEuPv94pHhjGVR46hhflS96SYKGdgYoIszjIkP2bCgysg3etqFXmUDzr4kd5ONo8gQg79P9vzFpXFQqN4t5IOZsg5bZ7bcbUV1/dsSGxYmsuaFl0I15Us3TNUM9sInaiLlylicsSGfc8qJD15RCOuNtqMHitZaCQRcgYmA+GFXAK8KXFRGt9g4emsGVKtSC3N2nODJb97OluSmnkLl6sGRn8Qmk73WFBPZyPKGXewA3ov+1pS9YqEZQp9E0MqQLtdb87WJTGAJmm5plVxK5nf/eKURnd5589aKVkyfeCFGvajDee7rQQGnuVWhoe7ga+A7hh0/TQumj1sP1Zjjevbkc3PbrFB4L5ghCbJzRO+1hnathlV/gcOPshztnxHaYGGlKYF2P1Xt4VBtVNfcnVN4dIM926154teI/8LEnUBqqf3IEJZHbEnH82WGipsDXVBP8oKQkbDirfqW0KDuvzSrkdkuaSO1LtTNAoxzAQJeQQXKns9CAfuDLlSVbRJH3mPDBTTjPBHJrH6wdwYp3y5ZDmPlvnnI651CA1lg+v+d7AmulkV8QYSZkOsdtuZu/grVUL6zJ7dJpOSn5I7Gn2CqPaHisEZmyi8d0Lgh6DeDbqjrdNg/REhlNrKzEH+iRwcUVN/JwnNbM8fFTuk5yWrKMGh+MeJBOFyWtp7x6XiP/SbHb/HuUkU3UH5DrosQrSYtS0ywSXlGPjQ3on6bTG40VSGPg7cRu2xbrxYMf+IuZ2wW6I0vvswzPKsoxg49J7vXq49Uo+JVpu2HQy/G3nMr8H/q93Hz51ThjvmveKAi/235XuLMeBLhHgL7Kn/WVUrASq9xSIP54u47OyRXMB1eFisqFvwP9ILGFCgJB407DpCJ8Fx8sdNA/HLJ865mlW1Z6oUdGbSPy4LGEgWdBBua4gBZlauMLkdNdaDYl8PiygIVJVa1op28Y3onZR4C2OV0Ag2qX/IrgCmv3NZ2PpbdqLQLwTKnsQp13uyR+QikNjY9qI7FPJ2mvxozHiYgxCc7wOZFEk1UrjwIwZqZYYdAjI6UrBpu7clI0076Cg2qe2YE46gadSWS/2pvIvqH3aBe8fscWwVgUzI10WAVhT98/GvE9BxUFS/JIfhuolNRHtz1AM/7nSRYnJVtYP2iqxkxvu+GPFlTAaUASa9E7HWlW1ERcVtIEdkkeDO61pfyzu3bMfe8Gmsd6uwt2ubc97/3kzDtQPmGjAXCpL2tcvFyrTdLEjqlstj+8Bn5B/9aLgGi9QDtnmpKBqgN/defLY7Rgj0ZfVJmF8l2GX6LMLu0zyHPo1BHL0+OFJnHqkKtZct4jI/1QDh9GENr9J+5aSuZNCQ0ex0OV2Taw3yjlabF5zl54TcrGAYMsft09Rmrqk2d9DAJHXITKv1IBcM0mv0Fmd3Kft12RavqFQOvA2BquqQ/KTIAHFfqmEjWamM0sCUqkExBcgto8Wdzf91h1etHQEBPE5DD5pryvcb0HNSsY8qEKGen/PqyI9HvEBOhqSnIl24Q3QuwQsfkQ+QGWus4WAe94E+TfCJenRqrlkxhQh17dNomjT908X2WueAvLW3VirForgXab0ZsW0FZX7c4g/4NLOfcw4TPn52PWGh+jH7N0zU8qygMgiqjZGxMD+XwvcUMc7BDtPtxmCrRFXLErss+V1wkCj26llRiw+DhQGxfIETXEdInF998yuZNl8bC7lwDuSnW4BAyW6cO5RdF1zW1DLNsQl+uGTro6oGQTxr6ua9OVjpLdOC+JwupBpa+pG3UYmxan5Y60F6yxqGk3iZm84agoOYaD4dutUG3Q9OIcRTTk87hzx9LdgFdr9R9Rjfj50t7QvUSWm4ZD42fPh/J60gerd5vDWTHq8+QMvIVwZ/lyPb7JdlqEaLClmIpnK+tVQ2DLv9NOov+VwOADI3gT8QaN+BZWiFiLd9HscDMUcE3CUD5ohAl86UG42lEeKA/9t4cQqs0RoWbqTJLxJ70C2TK3Pj8deQgR9oda3NEaIuI899vrSMlxDspedabhOm+KqgOOzlov9A0A37OCklp+38+VIIb3MwUtA3ZDaUbf7L2e8WcciAm2iGV71tUIOlbHfKkzgLk/GCpruoMYBwhPn3f+6KCLWk3D/jjEsO6B3WZdLBlLyphUJklLT5o+3+YBxsF3E7aG8PruldgFaEmGTqdL5vL8A56/QzmXx47i58C8kXURWBikRsutxIj5hCK2XWgT+N+xLn0HpJo3CMRNZx7MuWFgEe6yKvmZ/qxjfrnGKm280Bdf8HXXjNIMS6ajDcf1ubH0V33Ah2mXYG/FDY4zGlavVBH75YcQJ37/c5i+63sKZCLzjRSZyRmS4dufuEs4bWdVsIPkILFkDg8mz2bGCMOnuPSHBZVTxIt2YZ2oJjQryMPqSuIVfv/nHF7VrHi5LGWXtFPe+Es6pCDuD2DUeOJ2brg+jsiM30r1I2sIamSHcOaUoglJd37DPi93QSfGtreA+YOsDiJp1rVw3dAa0CW0WOXxSASkcU41uhZEfpYOdUbSJej/2InYfv0dW74zXWcvWsMiSbDEfzHjPtbaXgG322orR0OUMHMIwrkMDgkwp2SWk1RVS3OJc79ezBnEqWcA8fYBNOSq9e1HIC4KFlu6iv+7zMApyIXxpCiJrjhignzWU/2z1PV21CTqL6gp9Nxkl5WZHITyh/sAMbogVcYOm19IW12FtJ51xhHFiwOmqebMlMwojz8I51EnN5JJ6gvYxRKbNpPVfxWMLVY8J0OPdsQBhq3BdJugP6Rlau2Kh6StR3gJh/5TZ23Rb4VfnPEfveQIRavXOYF9699yPJehQrfQh1A9slEdKXij+DI4+5g6GwadicPL2Ti8C0iaPc452je8IUsxzQFvljrshI8Jk/6/PPM/7G6go7LwlBMAWYHWMdzmMcw5RO43jWPHkrqj8HwN4ENIn2yg42GI/ay17+Q+Pm7cMc2GfeLHTvCsmV2f1ptLQziuHLE+mm1idpNAqOyPDWtMMMbqBY+daDE+VvnVyqLhpLA6WS80z5FsJEhk2AaXYxa2gzi3V3EMpOCFSOzCvPJPbltbtjt1NoglQ70EleeA5HtrJV5slY0/PaFJBho3kUTnFe3fbspwPfFXgXV51r9JE8y021cKV8Tl0vejdlPlaAagmaPwNz1wT5jRVXci77FjsxjSoW8JuS+horXNdl/2X7Gd7Srk4ubp8YKCZe0Z0Y/ChBWrIs9JBbCkh7K2KV4+YKn/+kNYA4jBaogstE0YmX2QUUJ9FM0t9si+1SEBefNzNiaI3HQkhavlcv7sZQCgs5pue5wmZLj4r2W+1r2CvY6dkAKiVMqS5MGeawoK7BpPf7C+K0wE+yyceQffPCggPbVM91ZW6s5J+aw02AFAGM8d3SoYMPWnwz7/eTYS+gaHPQC9cfLpJD5h4+VMr5k1UIKrsUCvIS1SM1Vs9D0UX5g22gRKx0NzTlv7xgb1tcksg5I/1uguDtfovUrg1jLEY3s66GcbGUyBfCROzBxHU05cFOPBB7Huqmy9yuxLvYq5SYZGKByj5l05kr9BHXMNOZuHHWFZvLNNQGsbYNsZOluOJOoSeLqOqJ9Rl1yWlSz21kHSYJjXXK3rU0qSIHs/MipB/F8x3mm7V7sOE9Q/jXMJadrCxokdKDP4IvHJhULSuPaFaPnqc+5/oexinWDQrbgP2GA3HqPeBrm0LSohbIY20A0g7byX8oSXO3jl+H3/8hp8SFCU6Dk0r3qm03znJEazEHZj6hO/YNZz3faFBP24eutz+26oiLFlZ7AuGX/kydi17GG5+GIVPtLTYEogyQ+/EnZmhg+xkToZG9YWitjoc8IOj0mSel7rGToiwtbjbJf/L0p+vB36XX3CkpNyPHrRrvIU5ka/stTXiVVVW5X2TluzeLa+Krfn/BfSAXoO24WMr4p/teTIypQEWn/EA2Mb/mWujVhH7IiIwGEQ0PAnGOtNPBZzvmNFctzZZxg3MNgXuZsgV9giX4jSs+xVH2S8zEDrgoqf7Md7Tyw7fp5hIgODIvxA8w5ABXXHj6cxzbHfTVla/cnnWI5kZtrGgXcCIP72M8+TUV3cNO16tT/Td+yavNEUA+WxGeEQEXC/1t0351yfWcW6YBMHnMz8uzN5y5aHUsPBngboruLNozLWwRwUMzh+cJ/ceSPByDWXf/jrpNPJ4kYl3+ePy0y3u1GY+55xCD28xrneXq31Rzyh277UkAd6SxDjysxS8O/0T1hJQ5qBK+Qndry/QFz2Fruhggr/81/SgmdKcjUDcYw45WTCiByb9NtfftPCj02rK8AQffGW0qThNeIuFg25s233MU1npNtKJHRdolkpQBgfXu7R+oTbpDRwLZGiNX7LEX7KEJw+FClYzYlQrTffs+a0ggf+CpgCl0igPeGnb2yNgphYQ9lJfd85u4SQSx0ldY2jvb4vkDrg2QF2hXnZKKTgdY1KE60IEjptpgzGe1g3SRRrs/vgDSS3sSaO9xfySqrL3ZyH/Ch16XYkcGU5LaqPJ0M9RpljiMqcENHx4S7dmhtxi3vynGweNEV7RYMGL/0538lRf6+mL1tR70oBRXTANKQSJGMtz7YmK2Zf3ej8PHP0uSOdr30EtbWb1dp0GP5MpcpFs8FIqTzLlOw+G0LC0UOyLVgFVll12HJ/ncchnSMjk2LM+h34P882qwI5G0DiycAGy7sRL6Rw4mR1aKweCUgl6ls+iehg0tgehkktr1TeuEiFyRW/5yRqaZwisQOQur+4TptQNFXb1nXWxfL/2DZJ542HDjF4TnAGSXX59G4iN90HBL9UrX/o3l0vvfuqeG8oETyjGptJkV9RgNdcXfgIEqu/xuUkZBymbqflWopaCh3brS6JB4q4Ewd+6enDKwg9HelprdgIeD41oJewxTnNbQId5pNlhFpBznuuC+VTO5Y/n+qkV/s6ZLsj9/ZbRojOBjwkjlCisYM7TAWuTtaWohluyMzo08sb+iFp20MEVQp//C6FfV96Sd/MigbA5CxHzswlZusjOwfYur7uMuHLiICprsRuuDfjEqPytixP+qtKk6+MhvMeO8L/uylLQav3GMwlJswkOuF8Tj0cOgQigfIt1LPle18mlaDc3nyYw5mLdN+Bbd9lTeBJTAhy9VD/clu42A4YX/2IU3OoRfUenGFS7BuiWIvKcptqmCg2BR0m9Wn+U20OXvf0rMvOObVXXOkIdQBiIyn7TzXORkGzIrusORlgmmnjp7ouMQTqPXwesTgFIkQlaP+yWHcI9Pu9XEgjZAComRrWkNOhlkvuEFHhbL7iA5C3kzOz0Q8rw0izSEsvN9bROwOolwiO9gKT5eu7TpVzejqHK30v2Mh6RvpdTrqjo5v2vvfR8gKQf40Mq6Es3QraC1FMi6qsIB7oW11oR6N3MmTwF1us4cGzsOxboB5NzW3vLlmAPLnKuvbigh5XI71x0S2RwPuK4eSoqVHSadJqcFB+0kMzEN+ldFHoMN9bxFqAZ7tgp1MCrM335TKJhHyt29qY5SZZJ8wq9/okopiEB6hQT4wzcUEtyU4TEVy6oUuhT8nnNupWgbhiyW6/PrMd5XcTMDSeeA+QjC/0wiCEHRvBtci7kLrMJElXzK4W/vfh0aks/vyZZfWl6SrYeMgyIR9CqTVHFDquyqWuuIYbKqAkiqvQcJgyWacdyJSnYNnLHIMi6LYln9Bzpkg5v3kIlNmEk7ChVvkSABE+V2vNUXplbI2nA9Uqe6wd/o/Xac7VNWADOEJS1kHYkVC/KtrHSyfzYVnU4Iybt6v+TBzT0PgGlIwWHWeXb5+ffjjzn05YeeHNDlLvCIFxvz2c70+YgY3Q+/425isSV9ZwxulLxPXrGulBuHhLBv1DnkKTolhrBnc57C9CaGTXfuQcPoJcbTDxGkT/SHZ6sHf7AI4mvvEcHrNyesBkStFfr3M4pi/uTeTO8bYb2O/106Bgzo52kwcRxNBVt7ZDmOfYvtr3v0ADFqQfUvwdn8W7jSLJsCEdhAs7P3a+U7leHCvb38eYG+CxqoMZjuk3tQ7S/BmJ2m0CzyrM9lFADmJhMVy2Pm1TDtUzN3Gz2ouu+TJ8TuO16MhIvT2NE3fCC5c7Xh9NnSTNmcjl2pUY/9p1mraz5CXfbb5P4W8ZRymcRoueTtFzhJMjqNISeamLfqDi3o92xL3pIv2LayjixkIdcsXzsXzWJJitku/m3KrnKiCLTd3LMzE64os3ch/d0+KnH4DRlJVQDFkx82AtOR19FuhixGnS/PoSq4j5UT/LSJhzvv5okjWK3v03qm6mppwjEcwcGmMFmUoyhjBmpjDqg7gE5Tk5lTRw2SIVsWUqHXNQCsmS5fPJ6LcMUD7imLzYo/+yHofNtIYAY+6tB+x60wF0oTj8f38GzCGUKcIq1kRQE+m/jkK6egWPOxZLhPKCj9cQ4vZ6uBjlP1zBXeA56oNYdZX5ZLOwbFskjUnAhkZUmGpJuf+dpu5GEVGv/YMVlU+p2C2XjxvpmFjm4kkJk90PO1jE0N7KnVWVmVNPXxW7DQ+LXlS1N79REuCB2mL/sYskMRMwLjgQfCGHjvpe3EoUU+tvNFZw7H0QGyd/KMvxd6cc9OgIUMCUoDOEYVLnUK5KOR7sU28urcPWgAfMZ51dIsswwZyDz+Hvrf4GPaUT3bqPmhhCRc1cGANU0N6Zm3ab//nv8RexxRv9nm7jLZgLseksVRUxr8kwNblYfIpFyIFTY22JjdYv5fT2m+5GS84w3fQL+lj1z71I+DjkI4twUmK9c23ckmJqSpTBlJMkJJ+Vje664Wy+snKYo3oZCvEJsgf5YriW2WSj4sTKddh4hHtFB2sou48cMgMnkevqSRRtoXHVCdwMsMeP+lBrjH7WGIaa3A7DVEvpkLBK8rWidbOK0+rDmys0eFnl1eAYt42+/7lQ0UJXozRzcSfhhQ2XN5Rw6fILm33MjqjemTUKPMR3MwX7vH1q8kz1yeUvS8f/XMTictkrxHDRfkxys7C0dDK6JnhuVALAO2nQGyIGoB/joy2t915AeRU8RwPz0IqT0fTc51uXvQbLmlUyHJJwnI3AV5hKDkrEdam7J+5wfJQV+EbFF0hy+Q6Es7GkJkFoIKaC/3Xm6HQhZhXZUyjLKKWho42TA7w7lkRFn6LQCzNtmgoh5TsPyjzr5PnIFyYM6GPzxGare6jk+8U4PTqlypzjStiEI8TwxG9ggXH1vVPobXpjVR92figxhIC7YdR9lL6e2Erw9tekvyQuRVUSaTEOxOFjyVMMbYINHNuWTz5sEZ3t1Lyy5JpaOl1dNhpqFhtpRQSzDoNuVbgfqDRrQ5n6TPkP+Vj2Iu3BWSYbntjfyEnB3KM1TNFqjAZI1syD4WCkzu5dvCPjBNRJ48wGQklmeas64mToopg3ehHeCVXKwL3nqtoE3dk+OXoCNurumEQyJtgGq5Et8N+kaWUjatI6uJ6x3DnxOLtrynhP+7wRBYmYEWT86eHEN6Yc6f8prj1eRUe6dyQZh9spZdGcU/TmzlrEE5XcEX3EJVb2ik9J3U2DtbN9mgrJYel6N1C8TBJCzDvYNDOI0OaBrBmB2EJ7B1Y1iJhwEHRs6nVDWMytQa9QxIjCaMYQqZYcHK44iNVUhCDZK6pgckCnXqJf7z+KRewqG44Jv2AUoca9XyKpKbLHfpS2viaPjo2TDBkbL/GLkeeCH75moAovHO7MMOBSfFpfaglCqrMvCbyUSs5o6/gXZgs6InAjPxhoDbW6NUbLxTGtiiRA1/UFMIFh84bBNlPYwi4IwdtXHXdMpMiKx0uDx7Fjef4O6H4JJ54JV6NaqDFSm5I7Ez9qSVKthx0VOO3y3+sFHBZlkWozqFDWGSC8AO30xJMURMTEUv76+lJ7I0yjnp+S0pDiKU2Kt5gJCWjEe6dBcBS/RUORVV/rcWC1V2TvudFJo3C7n4OaxHS7Vlovi1fVtXDhZXeFXtgRRY1rCQJSWZEvZNn1Ik0VqaIig7fRdKoUCUjbc+cJ9e2bVIzrmph5LuyDfYT63YrwyjK2vfxBOlPczJ9Hts8FyYqHRsPgZKTiEyaxHQaDkngxHKgDUfCIiqu8tveROpjXFrKg+mlkisCZ2XmBCAAGcfJ+A5UON1b+/GELQQJKor2hThdxkKsbjnxENLrG+8K9X+iGe+3trrdmE9RspxPFcDRlTKD9sbrwCOJzF8qJ42oGctZe9vEYR1SOxBie2kCc9iNT36dpcW+cwl08eTun40qIwJSeaSqO4c53L2P6A6DTqD3RH4RSTsjhgK67GUYlSbo9qICB8zOalq9fQV/GBVXOqfxeH5FdTqskgvHPvgFYNG1Di1Nd/azRIUuJ7DcfzbtsezHmYeoXYiRwCJsAHafFwvf+DSrITr0p+8HZbHYSrNwmQxFIgorD5tQujNOhlL0AVo0OEiS7d5tN0QXjKsw9wqDwKouuOFT8jNHRiefFgWR+nuX5rH3x9HQabagLg+HnNCOvl1rvpP7Oe7oLtSObopfVsyQasHg+bg+UmJoJob2sLSzBQd7u7eC0lYbXEhyWzreSTqSttcUrtP8fB5Yu8jx4QdI8p2jMy6VTYLhYK3/2PP84JjdAkxzP0sgDaw79WQTtksIQZvtKBV3xtbFQiHL4lz9UO3jcJ42wAqVKTh1OHMb1YMz6WHkMrsW0wfCNEPxNpNcl3FvjVKpDtwkc6dfhZhzAfbLBqbgK5ypJJUi49YovzLCjjTv2dy9SRztlZd+JqHuOpyjgaXJZbUz0+oJkUe1G9Ne+S4lZUR/gGsWsXK7NhpVoN9C7pxuU7l0W55wwvVo1IsKjsmfpcV+Xp1lc8NGb0DRpUVOhQ2ss16DjyDazdZORbAd+zKFRcyFjXPIeiBScB3Y1oaVfYMhbEgJkqDtcIeMWxzEZp9Uz1a3zYRSXZaNyPHj0VYjEASR0UJ621pAGV5VtTXZS2+MtwbLMcHMgdSvtQtWc4idVB3XPQhZNBpJwyVEj9TFnKL28bsiKOo9Gka3up95sZbOZlXnDGN0zuMiMDXv4Dvp8or5wGxhpyOt58SFt/iFWF/KmJCS4tKMbUq+S7nIMjUKEpGxhO/0iWiq8mw9gRP96k6/e+vAV/ZfDGhSiMYojMjmaHoCa/Wt9AnigN/R6/4tjN3OTHGcUWmauMUQkRj1NccJsJ6DElE8+rbnZQ97DWXlnzRxVxWkmx0WGVIOoRkc3ZSu6gkK5V4lWARlBnnADdd9Axu09PZGw7OsPeDI1TWhc3Da51LsRatNbRda61c/ncOAUFpAio3mHX5IPWCIJGwy0E6fb0nHNQ07gpP6C/NUfS4efxt1z2Wr5JG0QFszbKpmFZRyvNhush65Adnf501A41B2NVxKoVpCq7KsgmujDk90zIsNDXel0z8vipZPk+g28O2JNSZpzjlg4DlXf6U6DpdvAmFhEllKIYa6KyYjUinuEdW/O48dzSuhtn4BFFAtK+8JSJmPfwC8IC0lXUBCu5K4phttBGs/cQV69Kn1Gxy6idyUDTApGFgibo0iWC6OITMSFW5b+Vc+VxGbGtCuHaj1kK4iXi9gTOV8UHssT5ZzPeBqubCiFwstIBEr5ZLlPmxxyMKBevPJNwqHmaR/FAQ2/fDBerXjpAC7WifgBn3e10YS+DJD8zd1GRx/8cz0NV9vi3ru7Jri6Q7zk4yJscjNQtEytzXX9S8rSJAJj+xke348sMXAmzuFdpO7v3+OP+Zp/HTY1sy9BOKjKnIys4lmLlMomaWqKZ1m8rrpfo6gFEx/v/ofQHSvyLI1E2lyYi8GdNXajI7HuxQSmnPYFtN7LPw8H/e6wbduMwzdbKxJ/Er5h3XNWikCIY7b3zo3OTSrBDynSvKs/RXccZouWy39G2TcKpMb8AQyt/5jC5HLzLTy24yGtXSr6RF+Kr3W+gWOvN4Xhfo6rMeHEAv+bJUzju1Fgdv2t7k1NWasn+yohJxKUIlDgvnfMgsP6mgaeT5cfxXMRVGNV92u3cfAfvXOZHt+E3MPtCuEuPxwUZUkQmTu2V1p9RVk7gk35l+WM+Nj5WreYmEHPqIgtyB10i0S9r7ttcpenvZJ84Z/mPr+7qUKPXg8sLeK5H4WpMbmbFXNeayrOVERqX2mpU8IhIMSsmrcp52+3Vs2VHx1qLD6Z7JZ9bYkGJ2ZpSZyXZ18HgzJBIAh2fmHvLb6TDzcckKKymqGyM5bIuf+D1ieNcrW0qQJ/fEYP0owLfQBy4Ngt8R0pHoT2YhQ+aOIdXbbTwp4Yw72X4inYvAKokevAVyFK3bK8gTvI6CAfxRDIhpZNdIAix+YrS7CJCfL6Bj8H11zkiupLHGXjfg9Wfra2uDh5n8UTFUZ+Ms+VPoUXi+35EsLhjmC6NNn8qZKIhJiU2OIOzUNXC6BK0D4yKMt8rqD8Dm/J5+YR2XFlZXnIhdOnzk8Sm4mxY2IFDuxZIBajg1v2yhrvBYwiMO+EjiIxsu2lDr8N/qCGHa2hplMFXtH409IEaoIWeo+IvtkBP/iWLCinIaRSEZ9sYT5kEjvbjiUb6i2bjO3sDN4x9l3Zr7s+UhAHjGgI+GAOJlKQFm2P6MtD8d12PbGRxYpjxg6vu7fMhRJ1NsCc7T9Erl5ZMnE/ECCA4hBmZE0O98iJJuQtV6v3+Hf80v79e7CgB/l8BqzKXbMuFVg4fl9QpeKcYKCAHNlFYkQ0z/Ec9hUak0TAIE08SJW7AmECvDvG5p3nJ9+F0UcWcYTaNGNZFdhPYvn1ye5BRUvt5309zPfGWYIv+ysZrkRN/BNEaKHjwAaoIi0kJpXgLvwEnyy0vGVRRxFoRwfC7WyS5wnAQK/caBUu1ZH4v8fjB2dC4WWBCddlaXOpVLChadDGkr29bMUYbVQRGNiugVXpQp7MZK4BGDKZPBD8rTfTh+AdUarSd8Jt3s4j9HkH2tZ/BbAcu8l/M8V3l5h3xRYuCW8aW6shAig4Hk4hpF/Eht1x8kfaqIWVkk6ib9IWgxRmMg6OMM2NwxmURfuC8L+fye6jdeAxe3IC/cLKA/dp2QQQ4cCtV3o78ymk8koFyw79EuuOZP0/tDh0gXts8zWdzAL2qahAQ2eE2lNpI7uWZZ5w2YGk154IU5XbEmL7k2muE0I5Ad1wsqLKJLVjg/EPbf6rPkrgJYS3ieVojTF3ZmLvNleiKoleWVdPb9rfx7HhByl88pSZaGHogbRXzjKYjVb+Ayw35UVmnpq6V317xpnG05PfY6T4jU2nvG+K0nElMxVg+7yUzQCsDZxU6YtE1yz7Et8Zg3Zbj0jXzQDhOmLQNyLF4hc45cKS51yASWDPnNZ2KlIrTacqxjqWmk7Rs3fHnTqqombjK8obcm+K8ZIdJGpHltZQz0fMawAawT283Ifsqzz2ou5u75N5MHd1TFURv/6cv7qDbypnawjIPX9B2nPNu4nztiHowXKFJUY2IkqjEbtVl0zcEX0hsm8HkLoLYY5nUt+Z91cNOuyEQ+D1vQabSLu/aJfDRK+2GuU23/8oJgRknaUpS3H2LCQCKZqfdeZjlKJ7NPu6sJoSihWtf9heWk2C5nC8ZrL74/OmrJDUQ/6DYrbSUmmMV/h25chAffgqBDx/v9I8m19y0XOm5Kx27tBHUqqav7Md/fZDqWOwGBMYDdPPA23aIjmF9MfEJQIcRnSxBHPlGMZ6s5AbNBcKuqjBXNTvj/fwy83yRkU1/7hkY/BJHMPkKjJwxrpUkQQ6+RCr695FFATiPWoemxjhC2XpYWf9zZdTZlTedurASrghIQhUe5bkx7uYuiYMNO/BwF86LEVOC+ZsKqjV3ClPMgDLGxpUHI+h42hQH+ydMB8xHQyo0lmBaOWhYcQ77k3+BgOTX/68nWclQRrtWYCa71Wa6G5iZLrov/+OMXDQn9Y1DUAl5fn76aC+1BxyEiAWmazmi2CIGiY8Db4o94BgK6BqvcnYAPD32VXeVP1pANQO4Swr9/YBcIjXpltTLfUopVW8JvAW1IuHCtF8DKIZgc+vfqzibNz0T8qavB4jIoLwHDqoz12k2zMFuh4VhMg/ojToImJA83LvwGBn/rnThibymrARBeEpVrivMObINFkK/pAn4jzV0+KMDEUwJ5ljL0vuLqSfEtUBJPkZhUIFkfPM/rIGa/hrn7QZlN4nms2f3/iWom/hPzPC/g4z+RH7on8Tb7PLnXMEGyayrG5TKPKz26mEcTvRADmXeB4yASDrENnbBZo0s2pWkCT5QA6leIFS/Niz1O6R5QuTpUPQuvoiW4PDUTG1f4tzTCljUM6sacjuNkoqUWWZxy7U4GFvVthWBGcPbMGbM1tyrlnhUi+8suato+VvXxoQJN+3wb18cZn+hm+vVdocJ0zae0ZEiXGjcnd/sW3XwR7IV8rX79AsFxAYkKqBDcTW2GG9b9jpKcgpAJmgfb36CrKyf18QaO8TVGSNT/YKX0XMZgLFc85yR1Tnvolcg0Z5xFmdridrB6gU5nIBxQ+EPnWJJkFDftJpBx4YbmsVHjAZxecLa9YrffOjDbNZganTW/wylmR8Q8wp/OoCo7nA5ItHsZjkzfLjlxOjPhwvvQxwRK2xaCYw67DXoU1WL5JritPM8quCeRz8/3N7/m6r7Z8YasV4Nl76ku+8cAJv37FoN1FfkDELKTylDjsfUqgjCYcZq3KoE15l/CDzinmMxShDfMzdkqPCeeMG6AQfCq/wTz0fkVnvkNc1x7QYTjMvxShYq1zKNzNOfsbVqOmMLcmVgplo1gbA0qbmXbjZD+FbfpbjE+FwPbsxKb39qT2RD59y07Uo6uBtttuRAENlfMYCibK/TFewNj5CgJWgAq4pk3kDRHWtGYiwKrzxY7yf5CiUI0wqelSFjGnSfiQ2lyqvmO1LMWg1WKXfnubJqNzVLTN8EpcdiSdcM4of9ZHTcrl8yTlChYUCgr3o6L21QQovftVpAtx/MCx79RwdPePtUyXoYQJ4BAjf00vjCaCIZIYBKom+0sLIm/NTK81m9TF0MndEQquJnRPWRFj6w4DwJJCpuGn+IE24gcnt0Rcx1bHoZ1vEGQCwru9JKaqBMaQLkU9QlApS7kuiXaFEldy289QOcrZ1FQYy/bA2CP20POxi9EeqV4vsMIwIEkctPwgTOg57qUCObs7aEq0Suk/4RB8JAPCftq2kJ6EJlb/bOORTteRqubFhY6OUgY8fV+69CYm9UN2SkQt+nReah9/nr7MEwnBnoZlXd5mlPO8lMZJv0VzuV0gahazEUmbbuYNp8cste4CkFIn3zPowSCJ6KfbTdCGOF8TglQ5cEbBD0pZSvoAbTk9XqLOuhGg+39uwbqLT9KamwMD1Siiy/oQMrvdi3xwq0Sm7XVYEttfMNkB3KzSSj7Jq7k1lLBTRnPArYeks3cQjm2ysa1IUuDF8AUQ9fcVxYUKn0ZZJI6jAcUw13IDs55D6ecXiupczd4gAVhpTUTY/bZMzqdiHeo0D5Gq2hSNAh8ofYmMHdpC82orVP8vLEO7G3gCnG7stylzmMCjzs5VTvm6u5/h3lOYR85xr3aXZv2rR1xhHSgr255ZODRJiMRrJSchgPPg2NF0MFe6xySQjhSFNSbvb4q3zAuuUAWR/zSQEGpzjLuPpFg8uCTKGE7UuGM2mZxn8AqjvTed1gx4WEBBGAh4u+IsLMEPkWu6TIwTFHqtVDZn2ntm5tIekR21mBjr6qXMGy6s7TqERabf1XncOG34Sr0GvPUHFOk0k/ZaOE/aV/wTW6JI4A3HawGJmpaZH+fapwQePakJh0F7qP/MmpPphuA/FmBWU8PjZJfR7nJb7K6aFaDBXkX0EpC5vWk=","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"cff5a8978d7972ec9513b32b2d7567593fb4f664","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file From d1870520fe6f2c717c2317582a29c5a6777ff49c Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 06:42:21 +1000 Subject: [PATCH 79/95] fix: decrypt scheduled webhook configuration --- Services/AlertService.php | 6 +-- tests/Feature/AlertWebhookEncryptionTest.php | 50 ++++++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/Services/AlertService.php b/Services/AlertService.php index 2e0ada2..bfab7b7 100644 --- a/Services/AlertService.php +++ b/Services/AlertService.php @@ -60,10 +60,8 @@ function (Collection $configs) use ( function (int $alertConfigId) use ( $schedulerHealth ): bool { - $config = DB::table( - 'ptero_alert_configs' - ) - ->where('id', $alertConfigId) + $config = AlertConfig::query() + ->whereKey($alertConfigId) ->where('is_active', true) ->first(); if ($config === null) { diff --git a/tests/Feature/AlertWebhookEncryptionTest.php b/tests/Feature/AlertWebhookEncryptionTest.php index 11a8f5e..349adef 100644 --- a/tests/Feature/AlertWebhookEncryptionTest.php +++ b/tests/Feature/AlertWebhookEncryptionTest.php @@ -3,7 +3,14 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Feature; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Event; +use Illuminate\Support\Facades\Http; +use Mockery; +use Paymenter\Extensions\Others\DynamicPterodactyl\Events\AlertDeliveryFailed; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\AlertConfig; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\AlertService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\ResourceCalculationService; +use Paymenter\Extensions\Others\DynamicPterodactyl\Services\WebhookEndpointPolicy; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; class AlertWebhookEncryptionTest extends LaravelTestCase @@ -46,4 +53,47 @@ public function test_migration_encrypts_existing_plaintext_without_double_encryp ); $this->assertSame($webhookUrl, AlertConfig::findOrFail($configId)->webhook_url); } + + public function test_scheduler_decrypts_persisted_webhook_url_before_delivery(): void + { + Event::fake(); + Http::fake(['*' => Http::response([], 204)]); + + $webhookUrl = 'https://hooks.example.com/capacity?token=stored-secret'; + $alertConfig = AlertConfig::create([ + 'location_id' => 13, + 'location_name' => 'SYD-1', + 'memory_warning_threshold' => 80, + 'memory_critical_threshold' => 90, + 'disk_warning_threshold' => 80, + 'disk_critical_threshold' => 90, + 'email_notifications' => false, + 'notification_emails' => [], + 'webhook_notifications' => true, + 'webhook_url' => $webhookUrl, + 'cooldown_minutes' => 60, + 'is_active' => true, + ]); + + $resourceService = Mockery::mock(ResourceCalculationService::class); + $resourceService->shouldReceive('getLocationAvailability')->once()->with(13)->andReturn([ + 'location_id' => 13, + 'location_name' => 'SYD-1', + 'total_capacity' => ['memory' => 100, 'disk' => 100], + 'total_allocated' => ['memory' => 95, 'disk' => 50], + ]); + $service = new AlertService( + $resourceService, + new WebhookEndpointPolicy( + static fn (string $host): array => ['93.184.216.34'] + ) + ); + + $this->assertSame(1, $service->checkCapacityAlerts()); + Http::assertSent( + fn ($request): bool => $request->url() === $webhookUrl + ); + $this->assertNotNull($alertConfig->fresh()->last_notification_at); + Event::assertNotDispatched(AlertDeliveryFailed::class); + } } From a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 06:42:57 +1000 Subject: [PATCH 80/95] docs: align contributor baseline --- CLAUDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 64896e5..7453104 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,7 @@ Filament 4, static-slider, and non-authoritative CPU designs. ## Current contract -- Paymenter 1.5.6, Filament 5, Livewire 4, PHP 8.3/8.4. +- Paymenter 1.5.7, Filament 5, Livewire 4, PHP 8.3/8.4. - Pterodactyl Panel and Wings 1.12.3 or newer. - Paymenter core owns slider rendering and pricing. - This extension owns live complete-vector stock, reservations, CPU policy, From 45e984c0da0c47675674b3477e8f3566c7a9610f Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 06:48:46 +1000 Subject: [PATCH 81/95] docs: refresh Qoder metadata and source pins --- .../en/content/API Reference/API Reference.md | 24 ++++++------- .../Architecture Overview.md | 34 +++++++++---------- .../en/content/Core Services/Core Services.md | 2 +- .qoder/repowiki/en/content/Deployment.md | 2 +- .qoder/repowiki/en/content/Event System.md | 2 +- .qoder/repowiki/en/content/Testing.md | 18 +++++----- .../repowiki/en/meta/repowiki-metadata.json | 2 +- 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index 44e3723..2c27f38 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -23,12 +23,12 @@ There are no standalone customer availability, pricing, reservation-create, reservation-confirm, or reservation-extend endpoints. Customer quote failures are generic; upstream bodies and internal exception messages are never returned. -[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php) +[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php) **Referenced Files in This Document** -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php) - [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) - [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) - [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) @@ -82,10 +82,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -124,7 +124,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L17-L22) - [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) - [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) @@ -141,7 +141,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L17-L40) - [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) - [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) @@ -151,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L17-L40) ### Endpoints @@ -190,7 +190,7 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L17-L40) - [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing @@ -229,7 +229,7 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L17-L22) - [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) @@ -313,7 +313,7 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L24-L30) - [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) - [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) @@ -343,7 +343,7 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L32-L40) - [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) @@ -378,7 +378,7 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L32-L40) - [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index d43d3ac..956ac93 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,17 +2,17 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/DynamicPterodactyl.php) -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/routes/api.php) -- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Services/PterodactylInventoryService.php) -- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Services/ResourceCalculationService.php) -- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Services/ResourceQuoteService.php) -- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Services/ReservationService.php) -- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Services/UpgradeReservationService.php) -- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Services/WebhookEndpointPolicy.php) -- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Models/NodeCapacityPolicy.php) -- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Listeners/CartItemCreatedListener.php) -- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/Listeners/CartItemDeletedListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Services/UpgradeReservationService.php) +- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Services/WebhookEndpointPolicy.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Listeners/CartItemDeletedListener.php) ## Reconciled Architecture @@ -136,9 +136,9 @@ in Paymenter core. For implementation-level detail, use these versioned repository guides: -- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/02-SERVICES.md) -- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/03-API.md) -- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/04-EVENTS.md) -- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/09-IMPLEMENTATION.md) -- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/DECISIONS.md) -- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/PROGRESS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index e5c5ac8..de7e068 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -17,7 +17,7 @@ `SchedulerHealthService`, and the audit/configuration services provide the supporting policies and operator visibility. -[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/02-SERVICES.md) +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/02-SERVICES.md) diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index 1c76aca..fd1a7b8 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -27,7 +27,7 @@ by the cross-repository workflow. Before enabling dynamic stock: The API key and alert webhook migrations encrypt stored credentials. Customer errors remain generic; detailed upstream failures belong only in protected logs. -[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/09-IMPLEMENTATION.md) +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/09-IMPLEMENTATION.md) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index 600b95a..5ddde28 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -15,7 +15,7 @@ companion lifecycle. The reconciled extension does not register cleanup, reconciliation, capacity alerts, and scheduler-lag checks are registered from `DynamicPterodactyl::boot()`. -[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/04-EVENTS.md) +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/04-EVENTS.md) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 5c05091..026dba7 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -14,14 +14,14 @@ process-private named-memory database and rejects inherited generated URIs in child processes. MySQL/MariaDB tests may use only the explicitly named `paymenter_test` database while `APP_ENV=testing`. -[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php) and -[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/TestDatabaseGuard.php) +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/TestDatabaseGuard.php) **Referenced Files in This Document** - [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) -- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php) - [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) - [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) - [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) @@ -86,7 +86,7 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) - [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) @@ -97,7 +97,7 @@ U --> AC **Section sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) @@ -142,7 +142,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -361,7 +361,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) @@ -383,7 +383,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -425,7 +425,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/cff5a8978d7972ec9513b32b2d7567593fb4f664/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 97fc54e..67434f5 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"22-52","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-14T19:47:29.0871327+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"48-49","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"77-78","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-14T19:47:29.0939215+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"12-100","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"45-51","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -\u003e 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -\u003e 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -\u003e f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -\u003e 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -\u003e 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -\u003e 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -\u003e 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -\u003e 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBW0kY68nN6yH347gACSKnGW/GaWsrfe1qmD5Vs4yiF9Bg4+cNg243x5/lrCPGe0ZLa727Kgt90Uf0qPTmGz2CCcagpDlxGuQ7KqPUQcnjLaS5faJVmqkBWfw6JX8uB8qtdCgeBozoNT8CS3Bl+VaFcrfo46PhuL+4MV4UlG69rB+KEYv2FlCDFDg9dsS+3XTkwBCvSqfvBNpmup+JH+w/q41CDiYfTbbURVO8q98JASJEHxb7rNSya1EFRu03Dndw5/hcunp6sW3i/mUBf3rxpXMRj7LhAAzagrVZYsK5LpuTLXislaMmRF+QNJZ+IT2lA/DQouhtUWc62leDrTc90zHDuF0e3jmfC8eu07DCVNzcVaikeY2HvQANYSq9rcpC9dzQDVFpKkVZPyhummuPO6U99ZLXQfwklIsKdCVTSZVinDVknwHBRxCYkuHbrR8PCWVfl3nrZOl4z3lC/mgPD7igYiJ64AUnOrpRNW3FBxgRf+8BvCrHeO/WIMVcJAbwWpx1XZdbGR+ktnHoWF73udn49QqG7nwtZCHkmejnF7RE14lQ8+LnaecPtPbDVehaKMSZUoX61sD47oraIoF5YU4E4zx2W6+7KWhB+NpL6ko1IG+UcHaD4hkEfJeD/2SeBD7vRpayej1ACgV5vne+TGzI7kZjsnKCjMqmxL4YD2RzBYMKD6LQL6+ubIXcmtFJAr/Qf1KdnxmlKveyXnZvX/ndj/g4n7iBoa+G06u5nlxnDftLOS1UX5Akt9Sa4ReIpPgc+Iu4fZiEvIogShhlx03pJAKPKeqY42rc4Hmh/zj2ffRkETYofbIvn6wCSpMGtQgaNCIsoTBzZqBh0tM7Ms2F9sOuNc6VOVytLWrAGs3Uj9mAw1cTz5V3dDkS8Iqc+2KwYHX1PPfXqBnFJ9XWfpzrzj1AUpLdt2Z96y1BKsDO8FeK7GHaIwMaAh0x3oc2MEQ48zBkemSFRqIbRb6rRjJaXwqbblx57l65FhBcMxFJxsPldnLySuNmXFfz1BkfSZ5DNpDxfbRaWAgJ5iptfMKdXbJy30ubNAJBkJhH4W4vLOQclfbDxGrO05ifqQbqraigV+gsHDqbEOiWWDQntcPu4du6DA+lClzPznkDuMn7ja/xjWhR8ohc2fY4GLWlOImAZLQEAyJmjJuZjDb+wqcLkwv/j9SeZbOJGELa6Y6Cr8itehW5lwWc5TsSfqavSxmD9CM2kCWNa9KxKdXaIxsUdn3AszUAdFlaPjG1P92QEIZMq5VR63US8SMFRS/lg2Bu/R10wr78W2ugpCg5hl4fZ5p/1vmKfSOK9ausuHQkeqqTABqn+iCT1Z7fU7QiEJ1KksgoDFkz8d4juqNhT7IjgBmnKpjlFLoMF070nLjTwO0MpA2l6ecAQhNFxkCTTgbwRAIdm91gS5JWtJnfYT+O23P17YXLCRKgLW9r5xM89j/ujErpG3/BIYXQkGGTGjTpO/lzd6VuHMlCDRwq73TZwT6AUgKKmb39ODafcEgXDC0Bwj49ZcUbc5EUw20RKYOccxNuKtBfilv6f7hbd8Hu0elrwUXFysMGHrQEIp5zXnFc3NBoJTtz5sGtxvwxy8KxeukwOhTloRknS/PinVWgDSl7tIsvU41/UPsEcjYzvczZ7nHfW+gpamwJoBNcYBOgGuCXoh+r/X+5NP4J0E8n/b2wCID44OPvacVG4V0qgjxQD4xvuliHGhoyte4iUvy5yOLrxbtwVmw5WBJUPAVwPgvGGRdqqVGnUW9k5T6rUGgAYhhHc5FTr9y4OibhX47uWd5eEv8IHnOhQT5/OyBAM1DOPcI1CQf0W6Pe/UObhm1662/8HXjlFAWsAJiyHi+I4iqPHBoOO9+l5Ng9s7uFUXtS6a2de/JIymAUP30+H8rrNsAGFKDIDiIVgJoPtOqSM+8eDo5CQvS/Wtf9VNIbJ0jbt8M9D79XxKedIjsFMGtgC4JPtycHOsQu3VsEvlFdhN60jr0Dd8w2Fa1hkc=","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"\u003c/think\u003e\n\n\u003cblog\u003e\n\n# Dynamic Pterodactyl Extension - Comprehensive Project Analysis\n\n## 1. Project Introduction\n\n### Purpose Statement\nDynamic Pterodactyl is a companion extension for Paymenter that enables dynamic resource allocation for Pterodactyl game server products. It provides real-time availability tracking, intelligent node selection, and temporary resource reservations during the checkout process.\n\n### Core Goals and Objectives\n- **Dynamic Resource Allocation**: Allow customers to select exact RAM, CPU, and Disk amounts using interactive sliders during checkout\n- **Real-Time Availability**: Query Pterodactyl API directly to ensure accurate resource availability without caching issues\n- **Resource Reservation System**: Implement 15-minute TTL-based reservations to prevent overselling during checkout\n- **Intelligent Node Selection**: Use weighted algorithms to allocate resources across optimal nodes based on memory, disk, and CPU headroom\n- **Seamless Integration**: Work alongside existing Pterodactyl server extension without reimplementing core functionality\n\n### Target Audience\n- Game server hosting providers using Paymenter and Pterodactyl\n- System administrators managing multi-node Pterodactyl installations\n- E-commerce platforms selling customizable game server resources\n\n## 2. Technical Architecture\n\n### Component Breakdown\n\nThe project follows a clean separation of concerns with distinct layers:\n\n```mermaid\ngraph TD\n A[Paymenter Core] --\u003e B[DynamicPterodactyl Extension]\n B --\u003e C[API Layer]\n B --\u003e D[Service Layer]\n B --\u003e E[Event Listeners]\n B --\u003e F[Admin Interface]\n \n C --\u003e G[AvailabilityController]\n C --\u003e H[PricingController]\n C --\u003e I[ReservationController]\n \n D --\u003e J[ResourceCalculationService]\n D --\u003e K[NodeSelectionService]\n D --\u003e L[ReservationService]\n D --\u003e M[AlertService]\n \n E --\u003e N[CartItemCreatedListener]\n E --\u003e O[InvoicePaidListener]\n E --\u003e P[ServiceCreatedListener]\n \n J --\u003e Q[Pterodactyl API]\n K --\u003e J\n L --\u003e K\n```\n\n### Design Patterns\n\n**Companion Extension Pattern**: The extension integrates with Paymenter's built-in Pterodactyl server extension rather than replacing it, ensuring automatic bug fixes and reduced maintenance overhead.\n\n**Event-Driven Architecture**: Uses Paymenter's event system to hook into cart and checkout lifecycle events for automatic reservation management.\n\n**Service-Oriented Architecture**: Business logic is encapsulated in dedicated services with clear responsibilities and dependency injection.\n\n**Repository Pattern**: Database operations are abstracted through service methods with proper transaction handling and pessimistic locking.\n\n### System Relationships\n\n```mermaid\nsequenceDiagram\n participant Client as Customer Browser\n participant API as API Layer\n participant Service as Service Layer\n participant DB as Database\n participant Ptero as Pterodactyl API\n \n Client-\u003e\u003e+API: GET /availability/{locationId}\n API-\u003e\u003e+Service: ResourceCalculationService::getLocationAvailability()\n Service-\u003e\u003e+Ptero: GET /api/application/nodes\n Ptero--\u003e\u003e-Service: Node data\n Service-\u003e\u003e+DB: Get pending reservations\n DB--\u003e\u003e-Service: Reservation data\n Service--\u003e\u003e-API: Availability data\n API--\u003e\u003e-Client: JSON response\n \n Client-\u003e\u003e+API: POST /reservation\n API-\u003e\u003e+Service: ReservationService::create()\n Service-\u003e\u003e+DB: lockForUpdate()\n Service-\u003e\u003e+Service: NodeSelectionService::selectBestNode()\n Service-\u003e\u003e+Ptero: Real-time availability check\n Service-\u003e\u003e+DB: Insert reservation\n DB--\u003e\u003e-Service: Reservation created\n Service--\u003e\u003e-API: Reservation token\n API--\u003e\u003e-Client: Token response\n```\n\n## 3. Key Implementation\n\n### Main Entry Points\n- **Extension Bootstrap**: `DynamicPterodactyl.php` - Registers routes, listeners, scheduled jobs, and policies\n- **Route Definitions**: `routes/api.php` - Defines RESTful endpoints for availability, pricing, and reservations\n\n### Core Modules\n\n**Service Layer**:\n- `Services/ResourceCalculationService.php` - Real-time Pterodactyl API integration for resource availability\n- `Services/NodeSelectionService.php` - Best-fit algorithm with weighted scoring for optimal node allocation\n- `Services/ReservationService.php` - Transactional reservation management with pessimistic locking\n- `Services/AlertService.php` - Capacity monitoring and notification system\n\n**Models**:\n- `Models/ResourceReservation.php` - Eloquent model for reservation tracking with scopes and relationships\n- `Models/AlertConfig.php` - Configuration for capacity alerts and thresholds\n\n**Controllers**:\n- `Http/Controllers/Api/AvailabilityController.php` - Handles availability queries and node details\n- `Http/Controllers/Api/PricingController.php` - Delegates pricing calculation to Paymenter core\n- `Http/Controllers/Api/ReservationController.php` - Manages reservation lifecycle (create, get, cancel, extend)\n\n### Configuration Approach\nConfiguration is managed through Paymenter's extension settings system with validation rules defined in the main extension class. Key configuration includes Pterodactyl API credentials, reservation TTL, and alert thresholds.\n\n### External Dependencies\n- **Pterodactyl Panel API**: Direct HTTP requests for real-time resource availability\n- **Paymenter Core**: Event system, models, and native slider components\n- **Laravel Framework**: Database transactions, scheduling, and HTTP client\n\n### Integration Points\n- **Paymenter Events**: Hooks into cart item creation, deletion, invoice payment, and service creation\n- **Database Schema**: Custom tables for reservations, audit logs, and alert configurations\n- **Admin Interface**: Filament-based dashboard for monitoring and management\n\n### Component Relationship Diagrams\n\n```mermaid\nclassDiagram\n class DynamicPterodactyl {\n +getConfig() array\n +boot() void\n +installed() void\n }\n \n class ReservationService {\n +create() array\n +confirm() bool\n +cancel() bool\n +extend() bool\n +cleanupExpired() int\n }\n \n class NodeSelectionService {\n +selectBestNode() ?array\n +getMaxAvailable() array\n }\n \n class ResourceCalculationService {\n +getLocationAvailability() array\n +calculateNodeAvailability() array\n +verifyAvailability() bool\n }\n \n class AlertService {\n +checkCapacityAlerts() void\n }\n \n DynamicPterodactyl --\u003e ReservationService\n DynamicPterodactyl --\u003e AlertService\n ReservationService --\u003e NodeSelectionService\n NodeSelectionService --\u003e ResourceCalculationService\n```\n\n## 4. Key Features\n\n### Functionality Overview\n\n**Real-Time Availability Checking**: Queries Pterodactyl API directly to provide accurate resource availability without cache staleness issues. Supports location-based filtering and per-node utilization metrics.\n\n**Intelligent Resource Allocation**: Implements a weighted best-fit algorithm that prioritizes memory headroom (50%), disk headroom (35%), and CPU headroom (15%) for optimal resource distribution across nodes.\n\n**Temporary Resource Reservations**: 15-minute TTL-based reservations prevent overselling during checkout with database-level pessimistic locking and automatic cleanup of expired reservations.\n\n**Dynamic Pricing Integration**: Leverages Paymenter's native pricing engine through `Plan::dynamicSliderBasePrice()` and `ConfigOption::calculateDynamicPriceDelta()` for consistent pricing calculations.\n\n**Administrative Dashboard**: Filament-based admin interface for monitoring reservations, capacity alerts, and system health with comprehensive audit logging.\n\n### Implementation Highlights\n\n**Event-Driven Checkout Flow**: Automatic reservation creation when cart items are added, confirmation upon successful payment, and cleanup when items are removed from cart.\n\n**Idempotent Operations**: Support for idempotency keys to handle duplicate requests gracefully during network retries or user actions.\n\n**Multi-Tier Alerting**: Configurable capacity alerts with cooldown periods and multiple notification channels for proactive capacity management.\n\n**Audit Trail**: Comprehensive logging of all administrative actions and system events for compliance and debugging purposes.\n\n### Feature Architecture Diagrams\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Available: Product Page Load\n Available --\u003e Reserved: User Selects Resources\n Reserved --\u003e Confirmed: Payment Successful\n Reserved --\u003e Expired: TTL Exceeded\n Reserved --\u003e Cancelled: User Removes Item\n Confirmed --\u003e [*]: Server Provisioned\n Expired --\u003e [*]: Cleanup Job\n Cancelled --\u003e [*]: Resource Released\n \n note right of Reserved\n 15-minute TTL\n Pessimistic locking\n Real-time verification\n end note\n```\n\n## 5. Conclusion and Recommendations\n\n### Project Architecture Summary\nDynamic Pterodactyl demonstrates excellent architectural decisions through its companion extension pattern, event-driven design, and service-oriented architecture. The project successfully balances complexity with maintainability while providing robust resource management capabilities for multi-node Pterodactyl deployments.\n\n### Architectural Strengths\n- **Clean Separation of Concerns**: Clear boundaries between API, service, and data layers\n- **Real-Time Data Access**: Eliminates cache staleness issues by querying Pterodactyl API directly\n- **Robust Concurrency Handling**: Database-level pessimistic locking prevents race conditions\n- **Extensible Design**: Event system allows easy integration with Paymenter's ecosystem\n- **Comprehensive Testing**: Well-structured test suite covering both unit and feature tests\n\n### Potential Improvement Areas\n- **Caching Strategy**: Consider implementing intelligent caching for frequently accessed node information to reduce API calls\n- **Performance Monitoring**: Add detailed performance metrics for API calls and database queries\n- **Configuration Validation**: Enhance configuration validation with more granular error reporting\n- **Documentation**: Expand inline documentation for complex business logic in services\n\n### Actionable Recommendations\n1. **Implement Circuit Breaker Pattern**: Add circuit breaker logic for Pterodactyl API calls to handle service degradation gracefully\n2. **Add Metrics Collection**: Integrate application performance monitoring for better observability\n3. **Enhance Error Handling**: Implement more specific exception types for better error categorization\n4. **Optimize Database Queries**: Review and optimize complex queries in reservation and availability services\n\n### Next Steps for Project Evolution\n- **Advanced Analytics**: Implement predictive capacity planning based on historical usage patterns\n- **Multi-Provider Support**: Extend support for additional game server panels beyond Pterodactyl\n- **Mobile Optimization**: Enhance mobile experience for resource selection and monitoring\n- **API Versioning**: Implement proper API versioning strategy for backward compatibility\n\nSources:\n- [DynamicPterodactyl.php](DynamicPterodactyl.php)\n- [README.md](README.md)\n- [02-SERVICES.md](02-SERVICES.md)\n- [03-API.md](03-API.md)\n- [Services/ReservationService.php](Services/ReservationService.php)\n- [Models/ResourceReservation.php](Models/ResourceReservation.php)\n- [database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php](database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php)\n- [Listeners/CartItemCreatedListener.php](Listeners/CartItemCreatedListener.php)\n\n\u003c/blog\u003e","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-14T18:27:43.9614238+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin\\\\\\n│ ├── Pages\\\\\\n│ │ ├── AuditLogPage.php\\n│ │ ├── Dashboard.php\\n│ │ ├── NodeMonitoring.php\\n│ │ └── SetupWizard.php\\n│ ├── Resources\\\\\\n│ │ ├── AlertConfigResource\\\\Pages\\\\\\n│ │ │ ├── CreateAlertConfig.php\\n│ │ │ ├── EditAlertConfig.php\\n│ │ │ └── ListAlertConfigs.php\\n│ │ ├── ReservationResource\\\\Pages\\\\\\n│ │ │ └── ListReservations.php\\n│ │ ├── AlertConfigResource.php\\n│ │ └── ReservationResource.php\\n│ └── AGENTS.md\\n├── Events\\\\\\n│ └── AlertDeliveryFailed.php\\n├── Http\\\\\\n│ ├── Controllers\\\\Api\\\\\\n│ │ ├── Admin\\\\\\n│ │ │ ├── AdminCapacityController.php\\n│ │ │ └── AdminReservationController.php\\n│ │ ├── AvailabilityController.php\\n│ │ ├── PricingController.php\\n│ │ └── ReservationController.php\\n│ ├── Middleware\\\\\\n│ │ └── EnsureUserIsAdmin.php\\n│ └── Requests\\\\\\n│ └── StoreReservationRequest.php\\n├── Listeners\\\\\\n│ ├── CartItemCreatedListener.php\\n│ ├── CartItemDeletedListener.php\\n│ ├── InvoicePaidListener.php\\n│ └── ServiceCreatedListener.php\\n├── Models\\\\\\n│ ├── Observers\\\\\\n│ │ └── AlertConfigObserver.php\\n│ ├── AlertConfig.php\\n│ ├── AlertDeliveryLog.php\\n│ ├── AuditLog.php\\n│ └── ResourceReservation.php\\n├── Notifications\\\\\\n│ ├── CapacityAlertNotification.php\\n│ └── ReservationShortfallNotification.php\\n├── Policies\\\\\\n│ └── ResourceReservationPolicy.php\\n├── Services\\\\\\n│ ├── Concerns\\\\\\n│ │ └── AuditsExtensionActions.php\\n│ ├── AlertService.php\\n│ ├── AuditLogService.php\\n│ ├── ConfigOptionSetupService.php\\n│ ├── NodeSelectionService.php\\n│ ├── ReservationService.php\\n│ ├── ResourceCalculationService.php\\n│ └── SliderConfigReaderService.php\\n├── database\\\\migrations\\\\\\n│ ├── 2025_01_01_000001_create_ptero_resource_reservations_table.php\\n│ ├── 2025_01_01_000002_create_ptero_pricing_configs_table.php\\n│ ├── 2025_01_01_000003_create_ptero_audit_logs_table.php\\n│ ├── 2025_01_01_000004_create_ptero_alert_configs_table.php\\n│ ├── 2025_01_01_000005_drop_ptero_pricing_configs_table.php\\n│ ├── 2026_04_22_000001_drop_released_from_reservation_status.php\\n│ ├── 2026_04_23_000001_add_idempotency_key_to_ptero_resource_reservations.php\\n│ └── 2026_04_26_000001_create_ptero_alert_delivery_log_table.php\\n├── resources\\\\views\\\\admin\\\\\\n│ ├── audit-log.blade.php\\n│ ├── dashboard.blade.php\\n│ ├── node-monitoring.blade.php\\n│ └── setup-wizard.blade.php\\n├── routes\\\\\\n│ └── api.php\\n├── tests\\\\\\n│ ├── Feature\\\\\\n│ │ ├── AdminApiTest.php\\n│ │ ├── AlertScheduleTest.php\\n│ │ ├── AvailabilityApiTest.php\\n│ │ ├── PricingPreviewParityTest.php\\n│ │ ├── ReservationApiTest.php\\n│ │ └── SetupWizardValidationTest.php\\n│ ├── Unit\\\\\\n│ │ ├── AlertConfigObserverTest.php\\n│ │ ├── AlertServiceTest.php\\n│ │ ├── CartItemDeletedListenerTest.php\\n│ │ ├── ConfigOptionSetupServiceTest.php\\n│ │ ├── InvoicePaidListenerTest.php\\n│ │ ├── NodeSelectionServiceTest.php\\n│ │ ├── ReservationServiceTest.php\\n│ │ ├── ResourceCalculationServiceTest.php\\n│ │ ├── SliderConfigReaderServiceTest.php\\n│ │ └── StoreReservationRequestTest.php\\n│ ├── AGENTS.md\\n│ ├── LaravelTestCase.php\\n│ ├── TestCase.php\\n│ └── bootstrap.php\\n├── AGENTS.md\\n├── DECISIONS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\\n\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"cff5a8978d7972ec9513b32b2d7567593fb4f664","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-14T19:47:29.7066198+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"dynamic-slider\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"18-36","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-18T06:47:36.6781350+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"20-29","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-18T06:47:36.6810540+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"31-45","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-18T06:47:36.6811344+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"13-45","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-18T06:47:36.6812160+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"27-33","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-18T06:47:36.6812690+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"# Dynamic Pterodactyl Extension Overview\n\nDynamic Pterodactyl is a companion extension for Paymenter 1.5.7 and its built-in Pterodactyl provisioner. It adds server-owned complete-vector RAM, CPU, disk, and allocation quotes; deterministic node selection; durable checkout and upgrade commitments; capacity alerts; and operator diagnostics without exposing node identity to customers.\n\n## Current architecture\n\n- `PterodactylInventoryService` performs strict, paginated, fail-closed reads of locations, nodes, servers, and allocations.\n- `ResourceCalculationService` combines live inventory with local commitments and explicit per-node `NodeCapacityPolicy` records. Stock Pterodactyl does not supply CPU capacity.\n- Paymenter cart events create and cancel short-lived holds. Payment, provisioning, renewal, cancellation, and upgrade state are coordinated by the companion Paymenter lifecycle rather than public reservation endpoints or invoice/service-created listeners in this extension.\n- Paid commitments and allocation claims are durable and idempotent. Dynamic products fail closed on malformed, incomplete, duplicated, orphaned, or unavailable inventory.\n- The Pterodactyl application key and alert webhook URLs are encrypted at rest. Webhooks are restricted to revalidated public HTTPS endpoints with pinned DNS and no redirects or proxies.\n- Deployment remains paused until the exact extension and Paymenter companion commits are reviewed, merged, migrated, and a real-panel staging lifecycle canary passes.\n\n## Documentation status\n\n`Architecture Overview/Architecture Overview.md` is the canonical current guide. The other 41 Qoder pages are preserved historical snapshots with explicit banners so earlier documentation and source trails remain available without overriding the reconciled architecture.","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-18T06:44:22.5011777+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin/\\n│ ├── Pages/{AuditLogPage,Dashboard,NodeMonitoring,SetupWizard}.php\\n│ └── Resources/{AlertConfigResource,NodeCapacityPolicyResource,ReservationResource}.php\\n├── Events/AlertDeliveryFailed.php\\n├── Http/\\n│ ├── Controllers/Api/{AvailabilityController,ResourceQuoteController,UpgradeQuoteController}.php\\n│ ├── Controllers/Api/Admin/{AdminCapacityController,AdminReservationController}.php\\n│ └── Middleware/EnsureUserIsAdmin.php\\n├── Listeners/{CartItemCreatedListener,CartItemDeletedListener}.php\\n├── Models/\\n│ ├── {AlertConfig,AlertDeliveryLog,AuditLog,NodeCapacityPolicy,ResourceReservation}.php\\n│ └── durable provisioning and upgrade lifecycle models\\n├── Notifications/\\n├── Policies/ResourceReservationPolicy.php\\n├── Services/\\n│ ├── {PterodactylInventoryService,ResourceCalculationService,ResourceQuoteService}.php\\n│ ├── {ReservationService,ReservationConfigurationService,UpgradeReservationService}.php\\n│ ├── {NodeSelectionService,NodeCapacityPolicyService,ConfigOptionSetupService}.php\\n│ ├── {AlertService,WebhookEndpointPolicy,SchedulerHealthService}.php\\n│ └── lifecycle integrity, audit, and operator-alert services\\n├── database/migrations/ # 22 forward migrations\\n├── resources/views/admin/\\n├── routes/api.php\\n├── tests/{Feature,Unit}/\\n├── .github/workflows/cross-repository-integration.yml\\n├── AGENTS.md\\n├── CLAUDE.md\\n├── DECISIONS.md\\n├── PROGRESS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-18T06:45:47.5747448+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"agent/rebase-pr22-on-pr23\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file From 39a161a75a73663b9358fe8a381b5144d7ae316e Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 07:15:00 +1000 Subject: [PATCH 82/95] fix: redact webhook transport failures --- Services/AlertService.php | 6 +- tests/Feature/AlertWebhookEncryptionTest.php | 65 ++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/Services/AlertService.php b/Services/AlertService.php index bfab7b7..3ce9794 100644 --- a/Services/AlertService.php +++ b/Services/AlertService.php @@ -302,13 +302,15 @@ private function sendNotifications(object $config, array $availability, array $a $channelsOk[] = 'webhook'; } catch (\Throwable $e) { + $error = 'Webhook delivery failed.'; Log::error('Webhook notification failed', [ 'alert_config_id' => $config->id, 'webhook_host' => parse_url($config->webhook_url, PHP_URL_HOST), - 'error' => $e->getMessage(), + 'error' => $error, + 'exception_class' => $e::class, ]); $channelsFailed[] = 'webhook'; - $lastError = $e->getMessage(); + $lastError = $error; } } diff --git a/tests/Feature/AlertWebhookEncryptionTest.php b/tests/Feature/AlertWebhookEncryptionTest.php index 349adef..f9e64bf 100644 --- a/tests/Feature/AlertWebhookEncryptionTest.php +++ b/tests/Feature/AlertWebhookEncryptionTest.php @@ -2,9 +2,11 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Feature; +use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Http; +use Illuminate\Support\Facades\Log; use Mockery; use Paymenter\Extensions\Others\DynamicPterodactyl\Events\AlertDeliveryFailed; use Paymenter\Extensions\Others\DynamicPterodactyl\Models\AlertConfig; @@ -15,6 +17,8 @@ class AlertWebhookEncryptionTest extends LaravelTestCase { + use DatabaseTransactions; + public function test_webhook_url_is_encrypted_at_rest(): void { $webhookUrl = 'https://hooks.example.com/path?token=storage-secret'; @@ -96,4 +100,65 @@ public function test_scheduler_decrypts_persisted_webhook_url_before_delivery(): $this->assertNotNull($alertConfig->fresh()->last_notification_at); Event::assertNotDispatched(AlertDeliveryFailed::class); } + + public function test_webhook_transport_failure_redacts_credentials_from_logs_and_delivery_history(): void + { + Event::fake(); + Log::spy(); + + $webhookUrl = 'https://hooks.example.com/capacity?token=transport-secret'; + Http::fake(static function () use ($webhookUrl): never { + throw new \RuntimeException("Connection failed for {$webhookUrl}"); + }); + $alertConfig = AlertConfig::create([ + 'location_id' => 14, + 'location_name' => 'SYD-2', + 'memory_warning_threshold' => 80, + 'memory_critical_threshold' => 90, + 'disk_warning_threshold' => 80, + 'disk_critical_threshold' => 90, + 'email_notifications' => false, + 'notification_emails' => [], + 'webhook_notifications' => true, + 'webhook_url' => $webhookUrl, + 'cooldown_minutes' => 60, + 'is_active' => true, + ]); + + $resourceService = Mockery::mock(ResourceCalculationService::class); + $resourceService->shouldReceive('getLocationAvailability')->once()->with(14)->andReturn([ + 'location_id' => 14, + 'location_name' => 'SYD-2', + 'total_capacity' => ['memory' => 100, 'disk' => 100], + 'total_allocated' => ['memory' => 95, 'disk' => 50], + ]); + $service = new AlertService( + $resourceService, + new WebhookEndpointPolicy( + static fn (string $host): array => ['93.184.216.34'] + ) + ); + + $this->assertSame(1, $service->checkCapacityAlerts()); + $lastError = DB::table('ptero_alert_delivery_log') + ->where('alert_config_id', $alertConfig->id) + ->value('last_error'); + + $this->assertSame('Webhook delivery failed.', $lastError); + $this->assertStringNotContainsString('transport-secret', (string) $lastError); + Log::shouldHaveReceived('error')->with( + 'Webhook notification failed', + Mockery::on(fn (array $context): bool => $context['alert_config_id'] === $alertConfig->id + && $context['webhook_host'] === 'hooks.example.com' + && $context['error'] === 'Webhook delivery failed.' + && ! str_contains( + json_encode($context, JSON_THROW_ON_ERROR), + 'transport-secret' + )) + ); + Event::assertDispatched( + AlertDeliveryFailed::class, + fn (AlertDeliveryFailed $event): bool => $event->deliveryLog->last_error === 'Webhook delivery failed.' + ); + } } From 5809c598ce20cd30475a24aa5ec016c77c7ae18d Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 07:18:47 +1000 Subject: [PATCH 83/95] docs: repin reviewed Qoder checkpoint --- .../en/content/API Reference/API Reference.md | 24 ++++++------ .../Architecture Overview.md | 39 +++++++++++-------- .../en/content/Core Services/Core Services.md | 2 +- .qoder/repowiki/en/content/Deployment.md | 2 +- .qoder/repowiki/en/content/Event System.md | 2 +- .qoder/repowiki/en/content/Testing.md | 18 ++++----- .../repowiki/en/meta/repowiki-metadata.json | 2 +- PROGRESS.md | 6 +++ 8 files changed, 53 insertions(+), 42 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index 2c27f38..962b18c 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -23,12 +23,12 @@ There are no standalone customer availability, pricing, reservation-create, reservation-confirm, or reservation-extend endpoints. Customer quote failures are generic; upstream bodies and internal exception messages are never returned. -[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php) +[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php) **Referenced Files in This Document** -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php) - [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) - [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) - [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) @@ -82,10 +82,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -124,7 +124,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L17-L22) - [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) - [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) @@ -141,7 +141,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L17-L40) - [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) - [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) @@ -151,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L17-L40) ### Endpoints @@ -190,7 +190,7 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L17-L40) - [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing @@ -229,7 +229,7 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L17-L22) - [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) @@ -313,7 +313,7 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L24-L30) - [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) - [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) @@ -343,7 +343,7 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L32-L40) - [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) @@ -378,7 +378,7 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L32-L40) - [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index 956ac93..dc5bf7e 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,17 +2,17 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/DynamicPterodactyl.php) -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/routes/api.php) -- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Services/PterodactylInventoryService.php) -- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Services/ResourceCalculationService.php) -- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Services/ResourceQuoteService.php) -- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Services/ReservationService.php) -- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Services/UpgradeReservationService.php) -- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Services/WebhookEndpointPolicy.php) -- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Models/NodeCapacityPolicy.php) -- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Listeners/CartItemCreatedListener.php) -- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/Listeners/CartItemDeletedListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Services/UpgradeReservationService.php) +- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Services/WebhookEndpointPolicy.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Listeners/CartItemDeletedListener.php) ## Reconciled Architecture @@ -24,6 +24,11 @@ their useful operational and historical detail is not lost. When an older page mentions a retired controller, listener, or API shape, this page and the current source take precedence. +The source links on this canonical page pin the latest code-bearing predecessor. +The metadata-only Qoder/Wiki publication commit is intentionally not +self-pinned because its Git object ID does not exist until after its content +has been committed. + DynamicPterodactyl remains a companion to Paymenter's built-in Pterodactyl extension. Paymenter owns products, invoices, services, and provisioning. This extension adds live resource quotes, short-lived capacity commitments, node and @@ -136,9 +141,9 @@ in Paymenter core. For implementation-level detail, use these versioned repository guides: -- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/02-SERVICES.md) -- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/03-API.md) -- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/04-EVENTS.md) -- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/09-IMPLEMENTATION.md) -- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/DECISIONS.md) -- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/PROGRESS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index de7e068..0239a51 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -17,7 +17,7 @@ `SchedulerHealthService`, and the audit/configuration services provide the supporting policies and operator visibility. -[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/02-SERVICES.md) +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/02-SERVICES.md) diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index fd1a7b8..e33e815 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -27,7 +27,7 @@ by the cross-repository workflow. Before enabling dynamic stock: The API key and alert webhook migrations encrypt stored credentials. Customer errors remain generic; detailed upstream failures belong only in protected logs. -[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/09-IMPLEMENTATION.md) +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/09-IMPLEMENTATION.md) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index 5ddde28..1738b84 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -15,7 +15,7 @@ companion lifecycle. The reconciled extension does not register cleanup, reconciliation, capacity alerts, and scheduler-lag checks are registered from `DynamicPterodactyl::boot()`. -[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/04-EVENTS.md) +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/04-EVENTS.md) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 026dba7..788a994 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -14,14 +14,14 @@ process-private named-memory database and rejects inherited generated URIs in child processes. MySQL/MariaDB tests may use only the explicitly named `paymenter_test` database while `APP_ENV=testing`. -[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php) and -[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/TestDatabaseGuard.php) +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/TestDatabaseGuard.php) **Referenced Files in This Document** - [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) -- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php) - [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) - [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) - [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) @@ -86,7 +86,7 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) - [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) @@ -97,7 +97,7 @@ U --> AC **Section sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) @@ -142,7 +142,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -361,7 +361,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) @@ -383,7 +383,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -425,7 +425,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 67434f5..5c3304c 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"18-36","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-18T06:47:36.6781350+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"20-29","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-18T06:47:36.6810540+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"31-45","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-18T06:47:36.6811344+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"13-45","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-18T06:47:36.6812160+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"27-33","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-18T06:47:36.6812690+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 22-52","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-86","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#247-289","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 247-289","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#48-49","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 48-49","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 77-78","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 12-100","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#45-51","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 45-51","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 452-498","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"# Dynamic Pterodactyl Extension Overview\n\nDynamic Pterodactyl is a companion extension for Paymenter 1.5.7 and its built-in Pterodactyl provisioner. It adds server-owned complete-vector RAM, CPU, disk, and allocation quotes; deterministic node selection; durable checkout and upgrade commitments; capacity alerts; and operator diagnostics without exposing node identity to customers.\n\n## Current architecture\n\n- `PterodactylInventoryService` performs strict, paginated, fail-closed reads of locations, nodes, servers, and allocations.\n- `ResourceCalculationService` combines live inventory with local commitments and explicit per-node `NodeCapacityPolicy` records. Stock Pterodactyl does not supply CPU capacity.\n- Paymenter cart events create and cancel short-lived holds. Payment, provisioning, renewal, cancellation, and upgrade state are coordinated by the companion Paymenter lifecycle rather than public reservation endpoints or invoice/service-created listeners in this extension.\n- Paid commitments and allocation claims are durable and idempotent. Dynamic products fail closed on malformed, incomplete, duplicated, orphaned, or unavailable inventory.\n- The Pterodactyl application key and alert webhook URLs are encrypted at rest. Webhooks are restricted to revalidated public HTTPS endpoints with pinned DNS and no redirects or proxies.\n- Deployment remains paused until the exact extension and Paymenter companion commits are reviewed, merged, migrated, and a real-panel staging lifecycle canary passes.\n\n## Documentation status\n\n`Architecture Overview/Architecture Overview.md` is the canonical current guide. The other 41 Qoder pages are preserved historical snapshots with explicit banners so earlier documentation and source trails remain available without overriding the reconciled architecture.","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-18T06:44:22.5011777+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin/\\n│ ├── Pages/{AuditLogPage,Dashboard,NodeMonitoring,SetupWizard}.php\\n│ └── Resources/{AlertConfigResource,NodeCapacityPolicyResource,ReservationResource}.php\\n├── Events/AlertDeliveryFailed.php\\n├── Http/\\n│ ├── Controllers/Api/{AvailabilityController,ResourceQuoteController,UpgradeQuoteController}.php\\n│ ├── Controllers/Api/Admin/{AdminCapacityController,AdminReservationController}.php\\n│ └── Middleware/EnsureUserIsAdmin.php\\n├── Listeners/{CartItemCreatedListener,CartItemDeletedListener}.php\\n├── Models/\\n│ ├── {AlertConfig,AlertDeliveryLog,AuditLog,NodeCapacityPolicy,ResourceReservation}.php\\n│ └── durable provisioning and upgrade lifecycle models\\n├── Notifications/\\n├── Policies/ResourceReservationPolicy.php\\n├── Services/\\n│ ├── {PterodactylInventoryService,ResourceCalculationService,ResourceQuoteService}.php\\n│ ├── {ReservationService,ReservationConfigurationService,UpgradeReservationService}.php\\n│ ├── {NodeSelectionService,NodeCapacityPolicyService,ConfigOptionSetupService}.php\\n│ ├── {AlertService,WebhookEndpointPolicy,SchedulerHealthService}.php\\n│ └── lifecycle integrity, audit, and operator-alert services\\n├── database/migrations/ # 22 forward migrations\\n├── resources/views/admin/\\n├── routes/api.php\\n├── tests/{Feature,Unit}/\\n├── .github/workflows/cross-repository-integration.yml\\n├── AGENTS.md\\n├── CLAUDE.md\\n├── DECISIONS.md\\n├── PROGRESS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"a9153bb6ebb0cea3f0fe936730b9406dbef8a2b8","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-18T06:45:47.5747448+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"agent/rebase-pr22-on-pr23\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"18-36","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-18T06:47:36.678135+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"20-29","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-18T06:47:36.681054+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"31-45","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-18T06:47:36.6811344+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"13-45","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-18T06:47:36.681216+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"27-33","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-18T06:47:36.681269+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#223-264","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 223-264","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#20-29","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 20-29","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#27-33","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-33","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"# Dynamic Pterodactyl Extension Overview\n\nDynamic Pterodactyl is a companion extension for Paymenter 1.5.7 and its built-in Pterodactyl provisioner. It adds server-owned complete-vector RAM, CPU, disk, and allocation quotes; deterministic node selection; durable checkout and upgrade commitments; capacity alerts; and operator diagnostics without exposing node identity to customers.\n\n## Current architecture\n\n- `PterodactylInventoryService` performs strict, paginated, fail-closed reads of locations, nodes, servers, and allocations.\n- `ResourceCalculationService` combines live inventory with local commitments and explicit per-node `NodeCapacityPolicy` records. Stock Pterodactyl does not supply CPU capacity.\n- Paymenter cart events create and cancel short-lived holds. Payment, provisioning, renewal, cancellation, and upgrade state are coordinated by the companion Paymenter lifecycle rather than public reservation endpoints or invoice/service-created listeners in this extension.\n- Paid commitments and allocation claims are durable and idempotent. Dynamic products fail closed on malformed, incomplete, duplicated, orphaned, or unavailable inventory.\n- The Pterodactyl application key and alert webhook URLs are encrypted at rest. Webhooks are restricted to revalidated public HTTPS endpoints with pinned DNS and no redirects or proxies.\n- Deployment remains paused until the exact extension and Paymenter companion commits are reviewed, merged, migrated, and a real-panel staging lifecycle canary passes.\n\n## Documentation status\n\n`Architecture Overview/Architecture Overview.md` is the canonical current guide. The other 41 Qoder pages are preserved historical snapshots with explicit banners so earlier documentation and source trails remain available without overriding the reconciled architecture.","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-18T06:44:22.5011777+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin/\\n│ ├── Pages/{AuditLogPage,Dashboard,NodeMonitoring,SetupWizard}.php\\n│ └── Resources/{AlertConfigResource,NodeCapacityPolicyResource,ReservationResource}.php\\n├── Events/AlertDeliveryFailed.php\\n├── Http/\\n│ ├── Controllers/Api/{AvailabilityController,ResourceQuoteController,UpgradeQuoteController}.php\\n│ ├── Controllers/Api/Admin/{AdminCapacityController,AdminReservationController}.php\\n│ └── Middleware/EnsureUserIsAdmin.php\\n├── Listeners/{CartItemCreatedListener,CartItemDeletedListener}.php\\n├── Models/\\n│ ├── {AlertConfig,AlertDeliveryLog,AuditLog,NodeCapacityPolicy,ResourceReservation}.php\\n│ └── durable provisioning and upgrade lifecycle models\\n├── Notifications/\\n├── Policies/ResourceReservationPolicy.php\\n├── Services/\\n│ ├── {PterodactylInventoryService,ResourceCalculationService,ResourceQuoteService}.php\\n│ ├── {ReservationService,ReservationConfigurationService,UpgradeReservationService}.php\\n│ ├── {NodeSelectionService,NodeCapacityPolicyService,ConfigOptionSetupService}.php\\n│ ├── {AlertService,WebhookEndpointPolicy,SchedulerHealthService}.php\\n│ └── lifecycle integrity, audit, and operator-alert services\\n├── database/migrations/ # 22 forward migrations\\n├── resources/views/admin/\\n├── routes/api.php\\n├── tests/{Feature,Unit}/\\n├── .github/workflows/cross-repository-integration.yml\\n├── AGENTS.md\\n├── CLAUDE.md\\n├── DECISIONS.md\\n├── PROGRESS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"39a161a75a73663b9358fe8a381b5144d7ae316e","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-18T06:45:47.5747448+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"agent/rebase-pr22-on-pr23\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file diff --git a/PROGRESS.md b/PROGRESS.md index 0047682..8809e69 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -18,6 +18,11 @@ Active implementation tracking. **Claude: Update this as you work.** All dp-NN backlog items are implemented. The completed successor is staged on `agent/rebase-pr22-on-pr23`; original draft PR #22 and prerequisite draft PR #23 remain unchanged for history. The exact Paymenter companion is published as draft PR #24. Mutagen deployment remains paused until the successor and companion are reviewed, merged, and separately authorized for deployment. +The Qoder metadata and canonical Wiki source links pin the latest code-bearing +predecessor. The later publication commit is intentionally not self-pinned: +its Git object ID cannot be known until the content containing that ID has +already been committed. + --- ## Completed @@ -82,6 +87,7 @@ All dp-NN backlog items are implemented. The completed successor is staged on `a 4. Replaced caller-selected SQLite test paths with the process-private `:temporary:` named-memory database workflow, including separate-process coverage. 5. Pinned the audited Paymenter companion, added the cross-repository PHP/SQLite/MariaDB matrix, pinned third-party workflow actions to immutable commits, and completed a read-only live Pterodactyl inventory smoke test. 6. Preserved all 42 migrated Qoder pages, marked superseded deep dives as historical, published the reconciled canonical architecture, and verified the standalone Wiki hierarchy, source links, and anchors. +7. Redacted credential-bearing webhook transport failures from application logs and alert delivery history, with persisted failure-path coverage. --- From 21901de86765a0c6df71435a9f0123f961aa9f2d Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 07:39:26 +1000 Subject: [PATCH 84/95] fix: reject deprecated IPv6 site-local webhooks --- Services/WebhookEndpointPolicy.php | 1 + tests/Unit/WebhookEndpointPolicyTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/Services/WebhookEndpointPolicy.php b/Services/WebhookEndpointPolicy.php index b86925f..1a411c9 100644 --- a/Services/WebhookEndpointPolicy.php +++ b/Services/WebhookEndpointPolicy.php @@ -39,6 +39,7 @@ final class WebhookEndpointPolicy '3fff::/20', '5f00::/16', 'fc00::/7', + 'fec0::/10', 'fe80::/10', 'ff00::/8', ]; diff --git a/tests/Unit/WebhookEndpointPolicyTest.php b/tests/Unit/WebhookEndpointPolicyTest.php index 9a4f30a..f0526b8 100644 --- a/tests/Unit/WebhookEndpointPolicyTest.php +++ b/tests/Unit/WebhookEndpointPolicyTest.php @@ -62,6 +62,7 @@ public static function blockedEndpointProvider(): array 'multicast IPv4' => ['https://hooks.example.com/path', ['224.0.0.1']], 'documentation IPv6' => ['https://hooks.example.com/path', ['2001:db8::1']], 'AS112 IPv6' => ['https://hooks.example.com/path', ['2620:4f:8000::1']], + 'deprecated site-local IPv6' => ['https://hooks.example.com/path', ['fec0::1']], 'multicast IPv6' => ['https://hooks.example.com/path', ['ff00::1']], 'mixed DNS response' => ['https://hooks.example.com/path', ['93.184.216.34', '10.0.0.1']], 'missing DNS response' => ['https://hooks.example.com/path', []], From 9ee48019c5a99822182c457e793af7422c1c9730 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 07:42:04 +1000 Subject: [PATCH 85/95] docs: repin IPv6 boundary checkpoint --- .../en/content/API Reference/API Reference.md | 24 ++++++------- .../Architecture Overview.md | 34 +++++++++---------- .../en/content/Core Services/Core Services.md | 2 +- .qoder/repowiki/en/content/Deployment.md | 2 +- .qoder/repowiki/en/content/Event System.md | 2 +- .qoder/repowiki/en/content/Testing.md | 18 +++++----- .../repowiki/en/meta/repowiki-metadata.json | 2 +- PROGRESS.md | 1 + 8 files changed, 43 insertions(+), 42 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index 962b18c..53e4a51 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -23,12 +23,12 @@ There are no standalone customer availability, pricing, reservation-create, reservation-confirm, or reservation-extend endpoints. Customer quote failures are generic; upstream bodies and internal exception messages are never returned. -[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php) +[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php) **Referenced Files in This Document** -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php) - [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) - [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) - [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) @@ -82,10 +82,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -124,7 +124,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L17-L22) - [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) - [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) @@ -141,7 +141,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L17-L40) - [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) - [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) @@ -151,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L17-L40) ### Endpoints @@ -190,7 +190,7 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L17-L40) - [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing @@ -229,7 +229,7 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L17-L22) - [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) @@ -313,7 +313,7 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L24-L30) - [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) - [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) @@ -343,7 +343,7 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L32-L40) - [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) @@ -378,7 +378,7 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L32-L40) - [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index dc5bf7e..caa5608 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,17 +2,17 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/DynamicPterodactyl.php) -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/routes/api.php) -- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Services/PterodactylInventoryService.php) -- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Services/ResourceCalculationService.php) -- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Services/ResourceQuoteService.php) -- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Services/ReservationService.php) -- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Services/UpgradeReservationService.php) -- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Services/WebhookEndpointPolicy.php) -- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Models/NodeCapacityPolicy.php) -- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Listeners/CartItemCreatedListener.php) -- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/Listeners/CartItemDeletedListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Services/UpgradeReservationService.php) +- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Services/WebhookEndpointPolicy.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Listeners/CartItemDeletedListener.php) ## Reconciled Architecture @@ -141,9 +141,9 @@ in Paymenter core. For implementation-level detail, use these versioned repository guides: -- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/02-SERVICES.md) -- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/03-API.md) -- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/04-EVENTS.md) -- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/09-IMPLEMENTATION.md) -- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/DECISIONS.md) -- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/PROGRESS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index 0239a51..ac014a7 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -17,7 +17,7 @@ `SchedulerHealthService`, and the audit/configuration services provide the supporting policies and operator visibility. -[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/02-SERVICES.md) +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/02-SERVICES.md) diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index e33e815..f4cc5af 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -27,7 +27,7 @@ by the cross-repository workflow. Before enabling dynamic stock: The API key and alert webhook migrations encrypt stored credentials. Customer errors remain generic; detailed upstream failures belong only in protected logs. -[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/09-IMPLEMENTATION.md) +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/09-IMPLEMENTATION.md) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index 1738b84..4cdfb12 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -15,7 +15,7 @@ companion lifecycle. The reconciled extension does not register cleanup, reconciliation, capacity alerts, and scheduler-lag checks are registered from `DynamicPterodactyl::boot()`. -[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/04-EVENTS.md) +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/04-EVENTS.md) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 788a994..fe7a497 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -14,14 +14,14 @@ process-private named-memory database and rejects inherited generated URIs in child processes. MySQL/MariaDB tests may use only the explicitly named `paymenter_test` database while `APP_ENV=testing`. -[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php) and -[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/TestDatabaseGuard.php) +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/TestDatabaseGuard.php) **Referenced Files in This Document** - [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) -- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php) - [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) - [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) - [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) @@ -86,7 +86,7 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) - [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) @@ -97,7 +97,7 @@ U --> AC **Section sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) @@ -142,7 +142,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -361,7 +361,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) @@ -383,7 +383,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -425,7 +425,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/39a161a75a73663b9358fe8a381b5144d7ae316e/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 5c3304c..5546f4b 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"18-36","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-18T06:47:36.678135+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"20-29","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-18T06:47:36.681054+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"31-45","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-18T06:47:36.6811344+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"13-45","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-18T06:47:36.681216+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"27-33","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-18T06:47:36.681269+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#223-264","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 223-264","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#20-29","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 20-29","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#27-33","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-33","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"# Dynamic Pterodactyl Extension Overview\n\nDynamic Pterodactyl is a companion extension for Paymenter 1.5.7 and its built-in Pterodactyl provisioner. It adds server-owned complete-vector RAM, CPU, disk, and allocation quotes; deterministic node selection; durable checkout and upgrade commitments; capacity alerts; and operator diagnostics without exposing node identity to customers.\n\n## Current architecture\n\n- `PterodactylInventoryService` performs strict, paginated, fail-closed reads of locations, nodes, servers, and allocations.\n- `ResourceCalculationService` combines live inventory with local commitments and explicit per-node `NodeCapacityPolicy` records. Stock Pterodactyl does not supply CPU capacity.\n- Paymenter cart events create and cancel short-lived holds. Payment, provisioning, renewal, cancellation, and upgrade state are coordinated by the companion Paymenter lifecycle rather than public reservation endpoints or invoice/service-created listeners in this extension.\n- Paid commitments and allocation claims are durable and idempotent. Dynamic products fail closed on malformed, incomplete, duplicated, orphaned, or unavailable inventory.\n- The Pterodactyl application key and alert webhook URLs are encrypted at rest. Webhooks are restricted to revalidated public HTTPS endpoints with pinned DNS and no redirects or proxies.\n- Deployment remains paused until the exact extension and Paymenter companion commits are reviewed, merged, migrated, and a real-panel staging lifecycle canary passes.\n\n## Documentation status\n\n`Architecture Overview/Architecture Overview.md` is the canonical current guide. The other 41 Qoder pages are preserved historical snapshots with explicit banners so earlier documentation and source trails remain available without overriding the reconciled architecture.","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-18T06:44:22.5011777+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin/\\n│ ├── Pages/{AuditLogPage,Dashboard,NodeMonitoring,SetupWizard}.php\\n│ └── Resources/{AlertConfigResource,NodeCapacityPolicyResource,ReservationResource}.php\\n├── Events/AlertDeliveryFailed.php\\n├── Http/\\n│ ├── Controllers/Api/{AvailabilityController,ResourceQuoteController,UpgradeQuoteController}.php\\n│ ├── Controllers/Api/Admin/{AdminCapacityController,AdminReservationController}.php\\n│ └── Middleware/EnsureUserIsAdmin.php\\n├── Listeners/{CartItemCreatedListener,CartItemDeletedListener}.php\\n├── Models/\\n│ ├── {AlertConfig,AlertDeliveryLog,AuditLog,NodeCapacityPolicy,ResourceReservation}.php\\n│ └── durable provisioning and upgrade lifecycle models\\n├── Notifications/\\n├── Policies/ResourceReservationPolicy.php\\n├── Services/\\n│ ├── {PterodactylInventoryService,ResourceCalculationService,ResourceQuoteService}.php\\n│ ├── {ReservationService,ReservationConfigurationService,UpgradeReservationService}.php\\n│ ├── {NodeSelectionService,NodeCapacityPolicyService,ConfigOptionSetupService}.php\\n│ ├── {AlertService,WebhookEndpointPolicy,SchedulerHealthService}.php\\n│ └── lifecycle integrity, audit, and operator-alert services\\n├── database/migrations/ # 22 forward migrations\\n├── resources/views/admin/\\n├── routes/api.php\\n├── tests/{Feature,Unit}/\\n├── .github/workflows/cross-repository-integration.yml\\n├── AGENTS.md\\n├── CLAUDE.md\\n├── DECISIONS.md\\n├── PROGRESS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"39a161a75a73663b9358fe8a381b5144d7ae316e","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-18T06:45:47.5747448+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"agent/rebase-pr22-on-pr23\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"18-36","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-18T06:47:36.678135+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"20-29","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-18T06:47:36.681054+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"31-45","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-18T06:47:36.6811344+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"13-45","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-18T06:47:36.681216+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"27-33","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-18T06:47:36.681269+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#223-264","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 223-264","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#20-29","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 20-29","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#27-33","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-33","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"# Dynamic Pterodactyl Extension Overview\n\nDynamic Pterodactyl is a companion extension for Paymenter 1.5.7 and its built-in Pterodactyl provisioner. It adds server-owned complete-vector RAM, CPU, disk, and allocation quotes; deterministic node selection; durable checkout and upgrade commitments; capacity alerts; and operator diagnostics without exposing node identity to customers.\n\n## Current architecture\n\n- `PterodactylInventoryService` performs strict, paginated, fail-closed reads of locations, nodes, servers, and allocations.\n- `ResourceCalculationService` combines live inventory with local commitments and explicit per-node `NodeCapacityPolicy` records. Stock Pterodactyl does not supply CPU capacity.\n- Paymenter cart events create and cancel short-lived holds. Payment, provisioning, renewal, cancellation, and upgrade state are coordinated by the companion Paymenter lifecycle rather than public reservation endpoints or invoice/service-created listeners in this extension.\n- Paid commitments and allocation claims are durable and idempotent. Dynamic products fail closed on malformed, incomplete, duplicated, orphaned, or unavailable inventory.\n- The Pterodactyl application key and alert webhook URLs are encrypted at rest. Webhooks are restricted to revalidated public HTTPS endpoints with pinned DNS and no redirects or proxies.\n- Deployment remains paused until the exact extension and Paymenter companion commits are reviewed, merged, migrated, and a real-panel staging lifecycle canary passes.\n\n## Documentation status\n\n`Architecture Overview/Architecture Overview.md` is the canonical current guide. The other 41 Qoder pages are preserved historical snapshots with explicit banners so earlier documentation and source trails remain available without overriding the reconciled architecture.","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-18T06:44:22.5011777+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin/\\n│ ├── Pages/{AuditLogPage,Dashboard,NodeMonitoring,SetupWizard}.php\\n│ └── Resources/{AlertConfigResource,NodeCapacityPolicyResource,ReservationResource}.php\\n├── Events/AlertDeliveryFailed.php\\n├── Http/\\n│ ├── Controllers/Api/{AvailabilityController,ResourceQuoteController,UpgradeQuoteController}.php\\n│ ├── Controllers/Api/Admin/{AdminCapacityController,AdminReservationController}.php\\n│ └── Middleware/EnsureUserIsAdmin.php\\n├── Listeners/{CartItemCreatedListener,CartItemDeletedListener}.php\\n├── Models/\\n│ ├── {AlertConfig,AlertDeliveryLog,AuditLog,NodeCapacityPolicy,ResourceReservation}.php\\n│ └── durable provisioning and upgrade lifecycle models\\n├── Notifications/\\n├── Policies/ResourceReservationPolicy.php\\n├── Services/\\n│ ├── {PterodactylInventoryService,ResourceCalculationService,ResourceQuoteService}.php\\n│ ├── {ReservationService,ReservationConfigurationService,UpgradeReservationService}.php\\n│ ├── {NodeSelectionService,NodeCapacityPolicyService,ConfigOptionSetupService}.php\\n│ ├── {AlertService,WebhookEndpointPolicy,SchedulerHealthService}.php\\n│ └── lifecycle integrity, audit, and operator-alert services\\n├── database/migrations/ # 22 forward migrations\\n├── resources/views/admin/\\n├── routes/api.php\\n├── tests/{Feature,Unit}/\\n├── .github/workflows/cross-repository-integration.yml\\n├── AGENTS.md\\n├── CLAUDE.md\\n├── DECISIONS.md\\n├── PROGRESS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"21901de86765a0c6df71435a9f0123f961aa9f2d","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-18T06:45:47.5747448+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"agent/rebase-pr22-on-pr23\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file diff --git a/PROGRESS.md b/PROGRESS.md index 8809e69..5c53722 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -88,6 +88,7 @@ already been committed. 5. Pinned the audited Paymenter companion, added the cross-repository PHP/SQLite/MariaDB matrix, pinned third-party workflow actions to immutable commits, and completed a read-only live Pterodactyl inventory smoke test. 6. Preserved all 42 migrated Qoder pages, marked superseded deep dives as historical, published the reconciled canonical architecture, and verified the standalone Wiki hierarchy, source links, and anchors. 7. Redacted credential-bearing webhook transport failures from application logs and alert delivery history, with persisted failure-path coverage. +8. Extended the webhook public-address boundary to reject deprecated IPv6 site-local space (`fec0::/10`) before transport pinning. --- From 872897b3b2d3f8232738fcae9e883bd3e53d5aa1 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 08:08:49 +1000 Subject: [PATCH 86/95] fix: reject IPv4-compatible IPv6 webhooks --- Services/WebhookEndpointPolicy.php | 1 + tests/Unit/WebhookEndpointPolicyTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/Services/WebhookEndpointPolicy.php b/Services/WebhookEndpointPolicy.php index 1a411c9..1b40607 100644 --- a/Services/WebhookEndpointPolicy.php +++ b/Services/WebhookEndpointPolicy.php @@ -28,6 +28,7 @@ final class WebhookEndpointPolicy '240.0.0.0/4', '::/128', '::1/128', + '::/96', '::ffff:0:0/96', '64:ff9b::/96', '64:ff9b:1::/48', diff --git a/tests/Unit/WebhookEndpointPolicyTest.php b/tests/Unit/WebhookEndpointPolicyTest.php index f0526b8..2de387b 100644 --- a/tests/Unit/WebhookEndpointPolicyTest.php +++ b/tests/Unit/WebhookEndpointPolicyTest.php @@ -58,6 +58,7 @@ public static function blockedEndpointProvider(): array 'benchmark IPv4' => ['https://198.18.0.1/path', ['198.18.0.1']], 'deprecated relay IPv4' => ['https://192.88.99.1/path', ['192.88.99.1']], 'loopback IPv6' => ['https://[::1]/path', ['::1']], + 'IPv4-compatible IPv6' => ['https://hooks.example.com/path', ['::7f00:1']], 'reserved IPv4' => ['https://hooks.example.com/path', ['203.0.113.10']], 'multicast IPv4' => ['https://hooks.example.com/path', ['224.0.0.1']], 'documentation IPv6' => ['https://hooks.example.com/path', ['2001:db8::1']], From 027b9b519b5e0638786114dd308765a2879ba1c5 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 08:10:45 +1000 Subject: [PATCH 87/95] docs: repin compatible IPv6 checkpoint --- .../en/content/API Reference/API Reference.md | 24 ++++++------- .../Architecture Overview.md | 34 +++++++++---------- .../en/content/Core Services/Core Services.md | 2 +- .qoder/repowiki/en/content/Deployment.md | 2 +- .qoder/repowiki/en/content/Event System.md | 2 +- .qoder/repowiki/en/content/Testing.md | 18 +++++----- .../repowiki/en/meta/repowiki-metadata.json | 2 +- PROGRESS.md | 1 + 8 files changed, 43 insertions(+), 42 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index 53e4a51..2b9b17a 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -23,12 +23,12 @@ There are no standalone customer availability, pricing, reservation-create, reservation-confirm, or reservation-extend endpoints. Customer quote failures are generic; upstream bodies and internal exception messages are never returned. -[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php) +[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php) **Referenced Files in This Document** -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php) - [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) - [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) - [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) @@ -82,10 +82,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -124,7 +124,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L17-L22) - [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) - [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) @@ -141,7 +141,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L17-L40) - [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) - [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) @@ -151,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L17-L40) ### Endpoints @@ -190,7 +190,7 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L17-L40) - [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing @@ -229,7 +229,7 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L17-L22) - [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) @@ -313,7 +313,7 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L24-L30) - [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) - [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) @@ -343,7 +343,7 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L32-L40) - [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) @@ -378,7 +378,7 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L32-L40) - [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index caa5608..bfa4a76 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,17 +2,17 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/DynamicPterodactyl.php) -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/routes/api.php) -- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Services/PterodactylInventoryService.php) -- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Services/ResourceCalculationService.php) -- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Services/ResourceQuoteService.php) -- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Services/ReservationService.php) -- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Services/UpgradeReservationService.php) -- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Services/WebhookEndpointPolicy.php) -- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Models/NodeCapacityPolicy.php) -- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Listeners/CartItemCreatedListener.php) -- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/Listeners/CartItemDeletedListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Services/UpgradeReservationService.php) +- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Services/WebhookEndpointPolicy.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Listeners/CartItemDeletedListener.php) ## Reconciled Architecture @@ -141,9 +141,9 @@ in Paymenter core. For implementation-level detail, use these versioned repository guides: -- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/02-SERVICES.md) -- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/03-API.md) -- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/04-EVENTS.md) -- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/09-IMPLEMENTATION.md) -- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/DECISIONS.md) -- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/PROGRESS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index ac014a7..6834be4 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -17,7 +17,7 @@ `SchedulerHealthService`, and the audit/configuration services provide the supporting policies and operator visibility. -[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/02-SERVICES.md) +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/02-SERVICES.md) diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index f4cc5af..ffe89c1 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -27,7 +27,7 @@ by the cross-repository workflow. Before enabling dynamic stock: The API key and alert webhook migrations encrypt stored credentials. Customer errors remain generic; detailed upstream failures belong only in protected logs. -[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/09-IMPLEMENTATION.md) +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/09-IMPLEMENTATION.md) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index 4cdfb12..3d0088e 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -15,7 +15,7 @@ companion lifecycle. The reconciled extension does not register cleanup, reconciliation, capacity alerts, and scheduler-lag checks are registered from `DynamicPterodactyl::boot()`. -[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/04-EVENTS.md) +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/04-EVENTS.md) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index fe7a497..9531be6 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -14,14 +14,14 @@ process-private named-memory database and rejects inherited generated URIs in child processes. MySQL/MariaDB tests may use only the explicitly named `paymenter_test` database while `APP_ENV=testing`. -[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php) and -[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/TestDatabaseGuard.php) +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/TestDatabaseGuard.php) **Referenced Files in This Document** - [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) -- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php) - [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) - [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) - [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) @@ -86,7 +86,7 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) - [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) @@ -97,7 +97,7 @@ U --> AC **Section sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) @@ -142,7 +142,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -361,7 +361,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) @@ -383,7 +383,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -425,7 +425,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/21901de86765a0c6df71435a9f0123f961aa9f2d/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 5546f4b..04c15b1 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"18-36","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-18T06:47:36.678135+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"20-29","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-18T06:47:36.681054+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"31-45","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-18T06:47:36.6811344+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"13-45","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-18T06:47:36.681216+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"27-33","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-18T06:47:36.681269+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#223-264","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 223-264","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#20-29","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 20-29","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#27-33","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-33","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBW0kY68nN6yH347gACSKnGW/GaWsrfe1qmD5Vs4yiF9Bg4+cNg243x5/lrCPGe0ZLa727Kgt90Uf0qPTmGz2CCcagpDlxGuQ7KqPUQcnjLaS5faJVmqkBWfw6JX8uB8qtdCgeBozoNT8CS3Bl+VaFcrfo46PhuL+4MV4UlG69rB+KEYv2FlCDFDg9dsS+3XTkwBCvSqfvBNpmup+JH+w/q41CDiYfTbbURVO8q98JASJEHxb7rNSya1EFRu03Dndw5/hcunp6sW3i/mUBf3rxpXMRj7LhAAzagrVZYsK5LpuTLXislaMmRF+QNJZ+IT2lA/DQouhtUWc62leDrTc90zHDuF0e3jmfC8eu07DCVNzcVaikeY2HvQANYSq9rcpC9dzQDVFpKkVZPyhummuPO6U99ZLXQfwklIsKdCVTSZVinDVknwHBRxCYkuHbrR8PCWVfl3nrZOl4z3lC/mgPD7igYiJ64AUnOrpRNW3FBxgRf+8BvCrHeO/WIMVcJAbwWpx1XZdbGR+ktnHoWF73udn49QqG7nwtZCHkmejnF7RE14lQ8+LnaecPtPbDVehaKMSZUoX61sD47oraIoF5YU4E4zx2W6+7KWhB+NpL6ko1IG+UcHaD4hkEfJeD/2SeBD7vRpayej1ACgV5vne+TGzI7kZjsnKCjMqmxL4YD2RzBYMKD6LQL6+ubIXcmtFJAr/Qf1KdnxmlKveyXnZvX/ndj/g4n7iBoa+G06u5nlxnDftLOS1UX5Akt9Sa4ReIpPgc+Iu4fZiEvIogShhlx03pJAKPKeqY42rc4Hmh/zj2ffRkETYofbIvn6wCSpMGtQgaNCIsoTBzZqBh0tM7Ms2F9sOuNc6VOVytLWrAGs3Uj9mAw1cTz5V3dDkS8Iqc+2KwYHX1PPfXqBnFJ9XWfpzrzj1AUpLdt2Z96y1BKsDO8FeK7GHaIwMaAh0x3oc2MEQ48zBkemSFRqIbRb6rRjJaXwqbblx57l65FhBcMxFJxsPldnLySuNmXFfz1BkfSZ5DNpDxfbRaWAgJ5iptfMKdXbJy30ubNAJBkJhH4W4vLOQclfbDxGrO05ifqQbqraigV+gsHDqbEOiWWDQntcPu4du6DA+lClzPznkDuMn7ja/xjWhR8ohc2fY4GLWlOImAZLQEAyJmjJuZjDb+wqcLkwv/j9SeZbOJGELa6Y6Cr8itehW5lwWc5TsSfqavSxmD9CM2kCWNa9KxKdXaIxsUdn3AszUAdFlaPjG1P92QEIZMq5VR63US8SMFRS/lg2Bu/R10wr78W2ugpCg5hl4fZ5p/1vmKfSOK9ausuHQkeqqTABqn+iCT1Z7fU7QiEJ1KksgoDFkz8d4juqNhT7IjgBmnKpjlFLoMF070nLjTwO0MpA2l6ecAQhNFxkCTTgbwRAIdm91gS5JWtJnfYT+O23P17YXLCRKgLW9r5xM89j/ujErpG3/BIYXQkGGTGjTpO/lzd6VuHMlCDRwq73TZwT6AUgKKmb39ODafcEgXDC0Bwj49ZcUbc5EUw20RKYOccxNuKtBfilv6f7hbd8Hu0elrwUXFysMGHrQEIp5zXnFc3NBoJTtz5sGtxvwxy8KxeukwOhTloRknS/PinVWgDSl7tIsvU41/UPsEcjYzvczZ7nHfW+gpamwJoBNcYBOgGuCXoh+r/X+5NP4J0E8n/b2wCID44OPvacVG4V0qgjxQD4xvuliHGhoyte4iUvy5yOLrxbtwVmw5WBJUPAVwPgvGGRdqqVGnUW9k5T6rUGgAYhhHc5FTr9y4OibhX47uWd5eEv8IHnOhQT5/OyBAM1DOPcI1CQf0W6Pe/UObhm1662/8HXjlFAWsAJiyHi+I4iqPHBoOO9+l5Ng9s7uFUXtS6a2de/JIymAUP30+H8rrNsAGFKDIDiIVgJoPtOqSM+8eDo5CQvS/Wtf9VNIbJ0jbt8M9D79XxKedIjsFMGtgC4JPtycHOsQu3VsEvlFdhN60jr0Dd8w2Fa1hkc=","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"# Dynamic Pterodactyl Extension Overview\n\nDynamic Pterodactyl is a companion extension for Paymenter 1.5.7 and its built-in Pterodactyl provisioner. It adds server-owned complete-vector RAM, CPU, disk, and allocation quotes; deterministic node selection; durable checkout and upgrade commitments; capacity alerts; and operator diagnostics without exposing node identity to customers.\n\n## Current architecture\n\n- `PterodactylInventoryService` performs strict, paginated, fail-closed reads of locations, nodes, servers, and allocations.\n- `ResourceCalculationService` combines live inventory with local commitments and explicit per-node `NodeCapacityPolicy` records. Stock Pterodactyl does not supply CPU capacity.\n- Paymenter cart events create and cancel short-lived holds. Payment, provisioning, renewal, cancellation, and upgrade state are coordinated by the companion Paymenter lifecycle rather than public reservation endpoints or invoice/service-created listeners in this extension.\n- Paid commitments and allocation claims are durable and idempotent. Dynamic products fail closed on malformed, incomplete, duplicated, orphaned, or unavailable inventory.\n- The Pterodactyl application key and alert webhook URLs are encrypted at rest. Webhooks are restricted to revalidated public HTTPS endpoints with pinned DNS and no redirects or proxies.\n- Deployment remains paused until the exact extension and Paymenter companion commits are reviewed, merged, migrated, and a real-panel staging lifecycle canary passes.\n\n## Documentation status\n\n`Architecture Overview/Architecture Overview.md` is the canonical current guide. The other 41 Qoder pages are preserved historical snapshots with explicit banners so earlier documentation and source trails remain available without overriding the reconciled architecture.","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-18T06:44:22.5011777+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin/\\n│ ├── Pages/{AuditLogPage,Dashboard,NodeMonitoring,SetupWizard}.php\\n│ └── Resources/{AlertConfigResource,NodeCapacityPolicyResource,ReservationResource}.php\\n├── Events/AlertDeliveryFailed.php\\n├── Http/\\n│ ├── Controllers/Api/{AvailabilityController,ResourceQuoteController,UpgradeQuoteController}.php\\n│ ├── Controllers/Api/Admin/{AdminCapacityController,AdminReservationController}.php\\n│ └── Middleware/EnsureUserIsAdmin.php\\n├── Listeners/{CartItemCreatedListener,CartItemDeletedListener}.php\\n├── Models/\\n│ ├── {AlertConfig,AlertDeliveryLog,AuditLog,NodeCapacityPolicy,ResourceReservation}.php\\n│ └── durable provisioning and upgrade lifecycle models\\n├── Notifications/\\n├── Policies/ResourceReservationPolicy.php\\n├── Services/\\n│ ├── {PterodactylInventoryService,ResourceCalculationService,ResourceQuoteService}.php\\n│ ├── {ReservationService,ReservationConfigurationService,UpgradeReservationService}.php\\n│ ├── {NodeSelectionService,NodeCapacityPolicyService,ConfigOptionSetupService}.php\\n│ ├── {AlertService,WebhookEndpointPolicy,SchedulerHealthService}.php\\n│ └── lifecycle integrity, audit, and operator-alert services\\n├── database/migrations/ # 22 forward migrations\\n├── resources/views/admin/\\n├── routes/api.php\\n├── tests/{Feature,Unit}/\\n├── .github/workflows/cross-repository-integration.yml\\n├── AGENTS.md\\n├── CLAUDE.md\\n├── DECISIONS.md\\n├── PROGRESS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"21901de86765a0c6df71435a9f0123f961aa9f2d","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-18T06:45:47.5747448+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"agent/rebase-pr22-on-pr23\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"18-36","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-18T06:47:36.678135+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"20-29","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-18T06:47:36.681054+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"31-45","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-18T06:47:36.6811344+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"13-45","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-18T06:47:36.681216+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"27-33","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-18T06:47:36.681269+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#223-264","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 223-264","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#20-29","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 20-29","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#27-33","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-33","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBW0kY68nN6yH347gACSKnGW/GaWsrfe1qmD5Vs4yiF9Bg4+cNg243x5/lrCPGe0ZLa727Kgt90Uf0qPTmGz2CCcagpDlxGuQ7KqPUQcnjLaS5faJVmqkBWfw6JX8uB8qtdCgeBozoNT8CS3Bl+VaFcrfo46PhuL+4MV4UlG69rB+KEYv2FlCDFDg9dsS+3XTkwBCvSqfvBNpmup+JH+w/q41CDiYfTbbURVO8q98JASJEHxb7rNSya1EFRu03Dndw5/hcunp6sW3i/mUBf3rxpXMRj7LhAAzagrVZYsK5LpuTLXislaMmRF+QNJZ+IT2lA/DQouhtUWc62leDrTc90zHDuF0e3jmfC8eu07DCVNzcVaikeY2HvQANYSq9rcpC9dzQDVFpKkVZPyhummuPO6U99ZLXQfwklIsKdCVTSZVinDVknwHBRxCYkuHbrR8PCWVfl3nrZOl4z3lC/mgPD7igYiJ64AUnOrpRNW3FBxgRf+8BvCrHeO/WIMVcJAbwWpx1XZdbGR+ktnHoWF73udn49QqG7nwtZCHkmejnF7RE14lQ8+LnaecPtPbDVehaKMSZUoX61sD47oraIoF5YU4E4zx2W6+7KWhB+NpL6ko1IG+UcHaD4hkEfJeD/2SeBD7vRpayej1ACgV5vne+TGzI7kZjsnKCjMqmxL4YD2RzBYMKD6LQL6+ubIXcmtFJAr/Qf1KdnxmlKveyXnZvX/ndj/g4n7iBoa+G06u5nlxnDftLOS1UX5Akt9Sa4ReIpPgc+Iu4fZiEvIogShhlx03pJAKPKeqY42rc4Hmh/zj2ffRkETYofbIvn6wCSpMGtQgaNCIsoTBzZqBh0tM7Ms2F9sOuNc6VOVytLWrAGs3Uj9mAw1cTz5V3dDkS8Iqc+2KwYHX1PPfXqBnFJ9XWfpzrzj1AUpLdt2Z96y1BKsDO8FeK7GHaIwMaAh0x3oc2MEQ48zBkemSFRqIbRb6rRjJaXwqbblx57l65FhBcMxFJxsPldnLySuNmXFfz1BkfSZ5DNpDxfbRaWAgJ5iptfMKdXbJy30ubNAJBkJhH4W4vLOQclfbDxGrO05ifqQbqraigV+gsHDqbEOiWWDQntcPu4du6DA+lClzPznkDuMn7ja/xjWhR8ohc2fY4GLWlOImAZLQEAyJmjJuZjDb+wqcLkwv/j9SeZbOJGELa6Y6Cr8itehW5lwWc5TsSfqavSxmD9CM2kCWNa9KxKdXaIxsUdn3AszUAdFlaPjG1P92QEIZMq5VR63US8SMFRS/lg2Bu/R10wr78W2ugpCg5hl4fZ5p/1vmKfSOK9ausuHQkeqqTABqn+iCT1Z7fU7QiEJ1KksgoDFkz8d4juqNhT7IjgBmnKpjlFLoMF070nLjTwO0MpA2l6ecAQhNFxkCTTgbwRAIdm91gS5JWtJnfYT+O23P17YXLCRKgLW9r5xM89j/ujErpG3/BIYXQkGGTGjTpO/lzd6VuHMlCDRwq73TZwT6AUgKKmb39ODafcEgXDC0Bwj49ZcUbc5EUw20RKYOccxNuKtBfilv6f7hbd8Hu0elrwUXFysMGHrQEIp5zXnFc3NBoJTtz5sGtxvwxy8KxeukwOhTloRknS/PinVWgDSl7tIsvU41/UPsEcjYzvczZ7nHfW+gpamwJoBNcYBOgGuCXoh+r/X+5NP4J0E8n/b2wCID44OPvacVG4V0qgjxQD4xvuliHGhoyte4iUvy5yOLrxbtwVmw5WBJUPAVwPgvGGRdqqVGnUW9k5T6rUGgAYhhHc5FTr9y4OibhX47uWd5eEv8IHnOhQT5/OyBAM1DOPcI1CQf0W6Pe/UObhm1662/8HXjlFAWsAJiyHi+I4iqPHBoOO9+l5Ng9s7uFUXtS6a2de/JIymAUP30+H8rrNsAGFKDIDiIVgJoPtOqSM+8eDo5CQvS/Wtf9VNIbJ0jbt8M9D79XxKedIjsFMGtgC4JPtycHOsQu3VsEvlFdhN60jr0Dd8w2Fa1hkc=","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"# Dynamic Pterodactyl Extension Overview\n\nDynamic Pterodactyl is a companion extension for Paymenter 1.5.7 and its built-in Pterodactyl provisioner. It adds server-owned complete-vector RAM, CPU, disk, and allocation quotes; deterministic node selection; durable checkout and upgrade commitments; capacity alerts; and operator diagnostics without exposing node identity to customers.\n\n## Current architecture\n\n- `PterodactylInventoryService` performs strict, paginated, fail-closed reads of locations, nodes, servers, and allocations.\n- `ResourceCalculationService` combines live inventory with local commitments and explicit per-node `NodeCapacityPolicy` records. Stock Pterodactyl does not supply CPU capacity.\n- Paymenter cart events create and cancel short-lived holds. Payment, provisioning, renewal, cancellation, and upgrade state are coordinated by the companion Paymenter lifecycle rather than public reservation endpoints or invoice/service-created listeners in this extension.\n- Paid commitments and allocation claims are durable and idempotent. Dynamic products fail closed on malformed, incomplete, duplicated, orphaned, or unavailable inventory.\n- The Pterodactyl application key and alert webhook URLs are encrypted at rest. Webhooks are restricted to revalidated public HTTPS endpoints with pinned DNS and no redirects or proxies.\n- Deployment remains paused until the exact extension and Paymenter companion commits are reviewed, merged, migrated, and a real-panel staging lifecycle canary passes.\n\n## Documentation status\n\n`Architecture Overview/Architecture Overview.md` is the canonical current guide. The other 41 Qoder pages are preserved historical snapshots with explicit banners so earlier documentation and source trails remain available without overriding the reconciled architecture.","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-18T06:44:22.5011777+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin/\\n│ ├── Pages/{AuditLogPage,Dashboard,NodeMonitoring,SetupWizard}.php\\n│ └── Resources/{AlertConfigResource,NodeCapacityPolicyResource,ReservationResource}.php\\n├── Events/AlertDeliveryFailed.php\\n├── Http/\\n│ ├── Controllers/Api/{AvailabilityController,ResourceQuoteController,UpgradeQuoteController}.php\\n│ ├── Controllers/Api/Admin/{AdminCapacityController,AdminReservationController}.php\\n│ └── Middleware/EnsureUserIsAdmin.php\\n├── Listeners/{CartItemCreatedListener,CartItemDeletedListener}.php\\n├── Models/\\n│ ├── {AlertConfig,AlertDeliveryLog,AuditLog,NodeCapacityPolicy,ResourceReservation}.php\\n│ └── durable provisioning and upgrade lifecycle models\\n├── Notifications/\\n├── Policies/ResourceReservationPolicy.php\\n├── Services/\\n│ ├── {PterodactylInventoryService,ResourceCalculationService,ResourceQuoteService}.php\\n│ ├── {ReservationService,ReservationConfigurationService,UpgradeReservationService}.php\\n│ ├── {NodeSelectionService,NodeCapacityPolicyService,ConfigOptionSetupService}.php\\n│ ├── {AlertService,WebhookEndpointPolicy,SchedulerHealthService}.php\\n│ └── lifecycle integrity, audit, and operator-alert services\\n├── database/migrations/ # 22 forward migrations\\n├── resources/views/admin/\\n├── routes/api.php\\n├── tests/{Feature,Unit}/\\n├── .github/workflows/cross-repository-integration.yml\\n├── AGENTS.md\\n├── CLAUDE.md\\n├── DECISIONS.md\\n├── PROGRESS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"872897b3b2d3f8232738fcae9e883bd3e53d5aa1","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-18T06:45:47.5747448+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"agent/rebase-pr22-on-pr23\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file diff --git a/PROGRESS.md b/PROGRESS.md index 5c53722..166d548 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -89,6 +89,7 @@ already been committed. 6. Preserved all 42 migrated Qoder pages, marked superseded deep dives as historical, published the reconciled canonical architecture, and verified the standalone Wiki hierarchy, source links, and anchors. 7. Redacted credential-bearing webhook transport failures from application logs and alert delivery history, with persisted failure-path coverage. 8. Extended the webhook public-address boundary to reject deprecated IPv6 site-local space (`fec0::/10`) before transport pinning. +9. Rejected legacy IPv4-compatible IPv6 space (`::/96`), preventing embedded loopback/private IPv4 destinations from reaching transport pinning. --- From 8b95295e4911d2be9d865ff000dfd7313278c3ab Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 08:30:55 +1000 Subject: [PATCH 88/95] fix: reject IANA dummy IPv6 webhooks --- Services/WebhookEndpointPolicy.php | 1 + tests/Unit/WebhookEndpointPolicyTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/Services/WebhookEndpointPolicy.php b/Services/WebhookEndpointPolicy.php index 1b40607..e6a6f24 100644 --- a/Services/WebhookEndpointPolicy.php +++ b/Services/WebhookEndpointPolicy.php @@ -33,6 +33,7 @@ final class WebhookEndpointPolicy '64:ff9b::/96', '64:ff9b:1::/48', '100::/64', + '100:0:0:1::/64', '2001::/23', '2001:db8::/32', '2002::/16', diff --git a/tests/Unit/WebhookEndpointPolicyTest.php b/tests/Unit/WebhookEndpointPolicyTest.php index 2de387b..91d380e 100644 --- a/tests/Unit/WebhookEndpointPolicyTest.php +++ b/tests/Unit/WebhookEndpointPolicyTest.php @@ -59,6 +59,7 @@ public static function blockedEndpointProvider(): array 'deprecated relay IPv4' => ['https://192.88.99.1/path', ['192.88.99.1']], 'loopback IPv6' => ['https://[::1]/path', ['::1']], 'IPv4-compatible IPv6' => ['https://hooks.example.com/path', ['::7f00:1']], + 'IANA dummy IPv6' => ['https://hooks.example.com/path', ['100:0:0:1::1']], 'reserved IPv4' => ['https://hooks.example.com/path', ['203.0.113.10']], 'multicast IPv4' => ['https://hooks.example.com/path', ['224.0.0.1']], 'documentation IPv6' => ['https://hooks.example.com/path', ['2001:db8::1']], From caa0ead2ed535779426735372a8412169920c431 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 08:32:18 +1000 Subject: [PATCH 89/95] docs: repin IANA registry checkpoint --- .../en/content/API Reference/API Reference.md | 24 ++++++------- .../Architecture Overview.md | 34 +++++++++---------- .../en/content/Core Services/Core Services.md | 2 +- .qoder/repowiki/en/content/Deployment.md | 2 +- .qoder/repowiki/en/content/Event System.md | 2 +- .qoder/repowiki/en/content/Testing.md | 18 +++++----- .../repowiki/en/meta/repowiki-metadata.json | 2 +- PROGRESS.md | 1 + 8 files changed, 43 insertions(+), 42 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index 2b9b17a..8ce42b7 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -23,12 +23,12 @@ There are no standalone customer availability, pricing, reservation-create, reservation-confirm, or reservation-extend endpoints. Customer quote failures are generic; upstream bodies and internal exception messages are never returned. -[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php) +[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php) **Referenced Files in This Document** -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php) - [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) - [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) - [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) @@ -82,10 +82,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -124,7 +124,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L17-L22) - [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) - [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) @@ -141,7 +141,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L17-L40) - [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) - [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) @@ -151,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L17-L40) ### Endpoints @@ -190,7 +190,7 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L17-L40) - [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing @@ -229,7 +229,7 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L17-L22) - [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) @@ -313,7 +313,7 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L24-L30) - [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) - [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) @@ -343,7 +343,7 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L32-L40) - [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) @@ -378,7 +378,7 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L32-L40) - [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index bfa4a76..da9089b 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,17 +2,17 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/DynamicPterodactyl.php) -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/routes/api.php) -- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Services/PterodactylInventoryService.php) -- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Services/ResourceCalculationService.php) -- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Services/ResourceQuoteService.php) -- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Services/ReservationService.php) -- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Services/UpgradeReservationService.php) -- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Services/WebhookEndpointPolicy.php) -- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Models/NodeCapacityPolicy.php) -- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Listeners/CartItemCreatedListener.php) -- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/Listeners/CartItemDeletedListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Services/UpgradeReservationService.php) +- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Services/WebhookEndpointPolicy.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Listeners/CartItemDeletedListener.php) ## Reconciled Architecture @@ -141,9 +141,9 @@ in Paymenter core. For implementation-level detail, use these versioned repository guides: -- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/02-SERVICES.md) -- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/03-API.md) -- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/04-EVENTS.md) -- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/09-IMPLEMENTATION.md) -- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/DECISIONS.md) -- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/PROGRESS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index 6834be4..2a849cd 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -17,7 +17,7 @@ `SchedulerHealthService`, and the audit/configuration services provide the supporting policies and operator visibility. -[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/02-SERVICES.md) +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/02-SERVICES.md) diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index ffe89c1..24d1ea6 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -27,7 +27,7 @@ by the cross-repository workflow. Before enabling dynamic stock: The API key and alert webhook migrations encrypt stored credentials. Customer errors remain generic; detailed upstream failures belong only in protected logs. -[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/09-IMPLEMENTATION.md) +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/09-IMPLEMENTATION.md) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index 3d0088e..2d8172f 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -15,7 +15,7 @@ companion lifecycle. The reconciled extension does not register cleanup, reconciliation, capacity alerts, and scheduler-lag checks are registered from `DynamicPterodactyl::boot()`. -[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/04-EVENTS.md) +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/04-EVENTS.md) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 9531be6..272efc8 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -14,14 +14,14 @@ process-private named-memory database and rejects inherited generated URIs in child processes. MySQL/MariaDB tests may use only the explicitly named `paymenter_test` database while `APP_ENV=testing`. -[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php) and -[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/TestDatabaseGuard.php) +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/TestDatabaseGuard.php) **Referenced Files in This Document** - [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) -- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php) - [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) - [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) - [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) @@ -86,7 +86,7 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) - [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) @@ -97,7 +97,7 @@ U --> AC **Section sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) @@ -142,7 +142,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -361,7 +361,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) @@ -383,7 +383,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -425,7 +425,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/872897b3b2d3f8232738fcae9e883bd3e53d5aa1/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index 04c15b1..f629e25 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"18-36","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-18T06:47:36.678135+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"20-29","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-18T06:47:36.681054+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"31-45","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-18T06:47:36.6811344+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"13-45","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-18T06:47:36.681216+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"27-33","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-18T06:47:36.681269+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#223-264","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 223-264","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#20-29","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 20-29","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#27-33","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-33","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"# Dynamic Pterodactyl Extension Overview\n\nDynamic Pterodactyl is a companion extension for Paymenter 1.5.7 and its built-in Pterodactyl provisioner. It adds server-owned complete-vector RAM, CPU, disk, and allocation quotes; deterministic node selection; durable checkout and upgrade commitments; capacity alerts; and operator diagnostics without exposing node identity to customers.\n\n## Current architecture\n\n- `PterodactylInventoryService` performs strict, paginated, fail-closed reads of locations, nodes, servers, and allocations.\n- `ResourceCalculationService` combines live inventory with local commitments and explicit per-node `NodeCapacityPolicy` records. Stock Pterodactyl does not supply CPU capacity.\n- Paymenter cart events create and cancel short-lived holds. Payment, provisioning, renewal, cancellation, and upgrade state are coordinated by the companion Paymenter lifecycle rather than public reservation endpoints or invoice/service-created listeners in this extension.\n- Paid commitments and allocation claims are durable and idempotent. Dynamic products fail closed on malformed, incomplete, duplicated, orphaned, or unavailable inventory.\n- The Pterodactyl application key and alert webhook URLs are encrypted at rest. Webhooks are restricted to revalidated public HTTPS endpoints with pinned DNS and no redirects or proxies.\n- Deployment remains paused until the exact extension and Paymenter companion commits are reviewed, merged, migrated, and a real-panel staging lifecycle canary passes.\n\n## Documentation status\n\n`Architecture Overview/Architecture Overview.md` is the canonical current guide. The other 41 Qoder pages are preserved historical snapshots with explicit banners so earlier documentation and source trails remain available without overriding the reconciled architecture.","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-18T06:44:22.5011777+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin/\\n│ ├── Pages/{AuditLogPage,Dashboard,NodeMonitoring,SetupWizard}.php\\n│ └── Resources/{AlertConfigResource,NodeCapacityPolicyResource,ReservationResource}.php\\n├── Events/AlertDeliveryFailed.php\\n├── Http/\\n│ ├── Controllers/Api/{AvailabilityController,ResourceQuoteController,UpgradeQuoteController}.php\\n│ ├── Controllers/Api/Admin/{AdminCapacityController,AdminReservationController}.php\\n│ └── Middleware/EnsureUserIsAdmin.php\\n├── Listeners/{CartItemCreatedListener,CartItemDeletedListener}.php\\n├── Models/\\n│ ├── {AlertConfig,AlertDeliveryLog,AuditLog,NodeCapacityPolicy,ResourceReservation}.php\\n│ └── durable provisioning and upgrade lifecycle models\\n├── Notifications/\\n├── Policies/ResourceReservationPolicy.php\\n├── Services/\\n│ ├── {PterodactylInventoryService,ResourceCalculationService,ResourceQuoteService}.php\\n│ ├── {ReservationService,ReservationConfigurationService,UpgradeReservationService}.php\\n│ ├── {NodeSelectionService,NodeCapacityPolicyService,ConfigOptionSetupService}.php\\n│ ├── {AlertService,WebhookEndpointPolicy,SchedulerHealthService}.php\\n│ └── lifecycle integrity, audit, and operator-alert services\\n├── database/migrations/ # 22 forward migrations\\n├── resources/views/admin/\\n├── routes/api.php\\n├── tests/{Feature,Unit}/\\n├── .github/workflows/cross-repository-integration.yml\\n├── AGENTS.md\\n├── CLAUDE.md\\n├── DECISIONS.md\\n├── PROGRESS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"872897b3b2d3f8232738fcae9e883bd3e53d5aa1","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-18T06:45:47.5747448+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"agent/rebase-pr22-on-pr23\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"18-36","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-18T06:47:36.678135+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"20-29","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-18T06:47:36.681054+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"31-45","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-18T06:47:36.6811344+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"13-45","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-18T06:47:36.681216+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"27-33","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-18T06:47:36.681269+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#223-264","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 223-264","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#20-29","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 20-29","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#27-33","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-33","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"# Dynamic Pterodactyl Extension Overview\n\nDynamic Pterodactyl is a companion extension for Paymenter 1.5.7 and its built-in Pterodactyl provisioner. It adds server-owned complete-vector RAM, CPU, disk, and allocation quotes; deterministic node selection; durable checkout and upgrade commitments; capacity alerts; and operator diagnostics without exposing node identity to customers.\n\n## Current architecture\n\n- `PterodactylInventoryService` performs strict, paginated, fail-closed reads of locations, nodes, servers, and allocations.\n- `ResourceCalculationService` combines live inventory with local commitments and explicit per-node `NodeCapacityPolicy` records. Stock Pterodactyl does not supply CPU capacity.\n- Paymenter cart events create and cancel short-lived holds. Payment, provisioning, renewal, cancellation, and upgrade state are coordinated by the companion Paymenter lifecycle rather than public reservation endpoints or invoice/service-created listeners in this extension.\n- Paid commitments and allocation claims are durable and idempotent. Dynamic products fail closed on malformed, incomplete, duplicated, orphaned, or unavailable inventory.\n- The Pterodactyl application key and alert webhook URLs are encrypted at rest. Webhooks are restricted to revalidated public HTTPS endpoints with pinned DNS and no redirects or proxies.\n- Deployment remains paused until the exact extension and Paymenter companion commits are reviewed, merged, migrated, and a real-panel staging lifecycle canary passes.\n\n## Documentation status\n\n`Architecture Overview/Architecture Overview.md` is the canonical current guide. The other 41 Qoder pages are preserved historical snapshots with explicit banners so earlier documentation and source trails remain available without overriding the reconciled architecture.","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-18T06:44:22.5011777+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin/\\n│ ├── Pages/{AuditLogPage,Dashboard,NodeMonitoring,SetupWizard}.php\\n│ └── Resources/{AlertConfigResource,NodeCapacityPolicyResource,ReservationResource}.php\\n├── Events/AlertDeliveryFailed.php\\n├── Http/\\n│ ├── Controllers/Api/{AvailabilityController,ResourceQuoteController,UpgradeQuoteController}.php\\n│ ├── Controllers/Api/Admin/{AdminCapacityController,AdminReservationController}.php\\n│ └── Middleware/EnsureUserIsAdmin.php\\n├── Listeners/{CartItemCreatedListener,CartItemDeletedListener}.php\\n├── Models/\\n│ ├── {AlertConfig,AlertDeliveryLog,AuditLog,NodeCapacityPolicy,ResourceReservation}.php\\n│ └── durable provisioning and upgrade lifecycle models\\n├── Notifications/\\n├── Policies/ResourceReservationPolicy.php\\n├── Services/\\n│ ├── {PterodactylInventoryService,ResourceCalculationService,ResourceQuoteService}.php\\n│ ├── {ReservationService,ReservationConfigurationService,UpgradeReservationService}.php\\n│ ├── {NodeSelectionService,NodeCapacityPolicyService,ConfigOptionSetupService}.php\\n│ ├── {AlertService,WebhookEndpointPolicy,SchedulerHealthService}.php\\n│ └── lifecycle integrity, audit, and operator-alert services\\n├── database/migrations/ # 22 forward migrations\\n├── resources/views/admin/\\n├── routes/api.php\\n├── tests/{Feature,Unit}/\\n├── .github/workflows/cross-repository-integration.yml\\n├── AGENTS.md\\n├── CLAUDE.md\\n├── DECISIONS.md\\n├── PROGRESS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"8b95295e4911d2be9d865ff000dfd7313278c3ab","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-18T06:45:47.5747448+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"agent/rebase-pr22-on-pr23\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file diff --git a/PROGRESS.md b/PROGRESS.md index 166d548..86f2bd7 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -90,6 +90,7 @@ already been committed. 7. Redacted credential-bearing webhook transport failures from application logs and alert delivery history, with persisted failure-path coverage. 8. Extended the webhook public-address boundary to reject deprecated IPv6 site-local space (`fec0::/10`) before transport pinning. 9. Rejected legacy IPv4-compatible IPv6 space (`::/96`), preventing embedded loopback/private IPv4 destinations from reaching transport pinning. +10. Reconciled the webhook denylist with the current IANA registry by rejecting the non-global dummy IPv6 prefix (`100:0:0:1::/64`). --- From 2c921a8956df479d7cde81b0b43c90db3d6b904c Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 08:51:34 +1000 Subject: [PATCH 90/95] test: cover ORCHID webhook rejection --- tests/Unit/WebhookEndpointPolicyTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Unit/WebhookEndpointPolicyTest.php b/tests/Unit/WebhookEndpointPolicyTest.php index 91d380e..19295ec 100644 --- a/tests/Unit/WebhookEndpointPolicyTest.php +++ b/tests/Unit/WebhookEndpointPolicyTest.php @@ -62,6 +62,7 @@ public static function blockedEndpointProvider(): array 'IANA dummy IPv6' => ['https://hooks.example.com/path', ['100:0:0:1::1']], 'reserved IPv4' => ['https://hooks.example.com/path', ['203.0.113.10']], 'multicast IPv4' => ['https://hooks.example.com/path', ['224.0.0.1']], + 'ORCHID IPv6' => ['https://hooks.example.com/path', ['2001:10::1']], 'documentation IPv6' => ['https://hooks.example.com/path', ['2001:db8::1']], 'AS112 IPv6' => ['https://hooks.example.com/path', ['2620:4f:8000::1']], 'deprecated site-local IPv6' => ['https://hooks.example.com/path', ['fec0::1']], From fe20627c71984aef6676a21fc7445c4fa5a19911 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 09:11:20 +1000 Subject: [PATCH 91/95] fix: redact inventory response bodies --- Services/PterodactylInventoryService.php | 5 ++-- .../Unit/PterodactylInventoryServiceTest.php | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Services/PterodactylInventoryService.php b/Services/PterodactylInventoryService.php index 97c05be..141ce5c 100644 --- a/Services/PterodactylInventoryService.php +++ b/Services/PterodactylInventoryService.php @@ -904,9 +904,8 @@ private function get(string $path, array $query): array if ($response->failed()) { \report(new \RuntimeException(sprintf( - 'Pterodactyl inventory API error (%d) body: %s', - $response->status(), - $response->body() + 'Pterodactyl inventory API error (%d).', + $response->status() ))); throw new \RuntimeException(sprintf( diff --git a/tests/Unit/PterodactylInventoryServiceTest.php b/tests/Unit/PterodactylInventoryServiceTest.php index 6b8d3f5..5c1900f 100644 --- a/tests/Unit/PterodactylInventoryServiceTest.php +++ b/tests/Unit/PterodactylInventoryServiceTest.php @@ -3,6 +3,7 @@ namespace Paymenter\Extensions\Others\DynamicPterodactyl\Tests\Unit; use App\Support\PanelEndpointIdentity; +use Illuminate\Contracts\Debug\ExceptionHandler; use Illuminate\Support\Facades\Http; use Paymenter\Extensions\Others\DynamicPterodactyl\Services\PterodactylInventoryService; use Paymenter\Extensions\Others\DynamicPterodactyl\Tests\LaravelTestCase; @@ -655,6 +656,31 @@ public function test_connection_check_exercises_nodes_servers_and_allocations_pe ); } + public function test_failed_inventory_response_is_sanitized_before_reporting(): void + { + $handler = \Mockery::mock(ExceptionHandler::class); + $handler->shouldReceive('report')->once()->with(\Mockery::on( + fn (\Throwable $exception): bool => $exception->getMessage() + === 'Pterodactyl inventory API error (500).' + && ! str_contains($exception->getMessage(), 'upstream-secret') + )); + $this->app->instance( + ExceptionHandler::class, + $handler + ); + + Http::fake([ + '*' => Http::response('provider error token=upstream-secret', 500), + ]); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage( + 'Pterodactyl inventory API error (500). Verify the application API key permissions.' + ); + + $this->inventory->locations(); + } + public function test_legacy_allocation_only_acknowledgement_is_not_a_capacity_guarantee(): void { $inventory = new PterodactylInventoryService([ From 4bb4edd359d602f7d8c201372af029e7a1e976ea Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 09:14:50 +1000 Subject: [PATCH 92/95] docs: repin sanitized inventory checkpoint --- .../en/content/API Reference/API Reference.md | 24 ++++++------- .../Architecture Overview.md | 34 +++++++++---------- .../en/content/Core Services/Core Services.md | 2 +- .qoder/repowiki/en/content/Deployment.md | 2 +- .qoder/repowiki/en/content/Event System.md | 2 +- .qoder/repowiki/en/content/Testing.md | 18 +++++----- .../repowiki/en/meta/repowiki-metadata.json | 2 +- 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/.qoder/repowiki/en/content/API Reference/API Reference.md b/.qoder/repowiki/en/content/API Reference/API Reference.md index 8ce42b7..98dd630 100644 --- a/.qoder/repowiki/en/content/API Reference/API Reference.md +++ b/.qoder/repowiki/en/content/API Reference/API Reference.md @@ -23,12 +23,12 @@ There are no standalone customer availability, pricing, reservation-create, reservation-confirm, or reservation-extend endpoints. Customer quote failures are generic; upstream bodies and internal exception messages are never returned. -[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php) +[Current routes](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/routes/api.php) **Referenced Files in This Document** -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/routes/api.php) - [AvailabilityController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php) - [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) - [ReservationController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php) @@ -82,10 +82,10 @@ F --> I["AvailabilityController
GET /availability/{locationId}/nodes"] ``` **Diagram sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/routes/api.php#L17-L40) **Section sources** -- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L1-L40) +- [routes/api.php:1-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/routes/api.php#L1-L40) ## Core Components - AvailabilityController: Returns per-location availability aggregates and, when authenticated as admin, detailed node information. @@ -124,7 +124,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n ``` **Diagram sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/routes/api.php#L17-L22) - [AvailabilityController.php:22-52](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L52) - [ResourceCalculationService.php:26-67](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L26-L67) @@ -141,7 +141,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Resource-level authorization uses ResourceReservationPolicy to enforce ownership for view/cancel/extend actions. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/routes/api.php#L17-L40) - [EnsureUserIsAdmin.php:9-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Middleware/EnsureUserIsAdmin.php#L9-L22) - [ResourceReservationPolicy.php:9-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Policies/ResourceReservationPolicy.php#L9-L69) @@ -151,7 +151,7 @@ AvailCtrl-->>Client : {success,data : {location_id,max_memory,max_cpu,max_disk,n - Admin endpoints: 30 requests per minute per client. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/routes/api.php#L17-L40) ### Endpoints @@ -190,7 +190,7 @@ Notes: - Node-level detail (including names and per-node capacity) is restricted to admin. **Section sources** -- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L17-L40) +- [routes/api.php:17-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/routes/api.php#L17-L40) - [AvailabilityController.php:22-69](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/AvailabilityController.php#L22-L69) #### Pricing @@ -229,7 +229,7 @@ Important: - This extension does not compute prices itself; it delegates to Paymenter core’s dynamic slider pricing. **Section sources** -- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L17-L22) +- [routes/api.php:17-22](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/routes/api.php#L17-L22) - [PricingController.php:24-157](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php#L24-L157) - [StoreReservationRequest.php:38-112](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L38-L112) @@ -313,7 +313,7 @@ Notes: - Reservation lifecycle is strictly pending → confirmed | expired | cancelled. **Section sources** -- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L24-L30) +- [routes/api.php:24-30](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/routes/api.php#L24-L30) - [ReservationController.php:24-137](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/ReservationController.php#L24-L137) - [StoreReservationRequest.php:10-162](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php#L10-L162) - [ReservationService.php:43-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L43-L141) @@ -343,7 +343,7 @@ Notes: - Aggregates include per-node availability derived from Pterodactyl servers and pending reservations. **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/routes/api.php#L32-L40) - [AdminCapacityController.php:17-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminCapacityController.php#L17-L62) - [ResourceCalculationService.php:69-141](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ResourceCalculationService.php#L69-L141) @@ -378,7 +378,7 @@ Notes: - 409: reservation not in pending state or status changed concurrently **Section sources** -- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php#L32-L40) +- [routes/api.php:32-40](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/routes/api.php#L32-L40) - [AdminReservationController.php:18-75](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/Admin/AdminReservationController.php#L18-L75) - [ReservationService.php:208-241](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L208-L241) diff --git a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md index da9089b..21dc198 100644 --- a/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md +++ b/.qoder/repowiki/en/content/Architecture Overview/Architecture Overview.md @@ -2,17 +2,17 @@ **Referenced Files in This Document** -- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/DynamicPterodactyl.php) -- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/routes/api.php) -- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Services/PterodactylInventoryService.php) -- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Services/ResourceCalculationService.php) -- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Services/ResourceQuoteService.php) -- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Services/ReservationService.php) -- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Services/UpgradeReservationService.php) -- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Services/WebhookEndpointPolicy.php) -- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Models/NodeCapacityPolicy.php) -- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Listeners/CartItemCreatedListener.php) -- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/Listeners/CartItemDeletedListener.php) +- [DynamicPterodactyl.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/DynamicPterodactyl.php) +- [routes/api.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/routes/api.php) +- [Services/PterodactylInventoryService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/Services/PterodactylInventoryService.php) +- [Services/ResourceCalculationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/Services/ResourceCalculationService.php) +- [Services/ResourceQuoteService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/Services/ResourceQuoteService.php) +- [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/Services/ReservationService.php) +- [Services/UpgradeReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/Services/UpgradeReservationService.php) +- [Services/WebhookEndpointPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/Services/WebhookEndpointPolicy.php) +- [Models/NodeCapacityPolicy.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/Models/NodeCapacityPolicy.php) +- [Listeners/CartItemCreatedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/Listeners/CartItemCreatedListener.php) +- [Listeners/CartItemDeletedListener.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/Listeners/CartItemDeletedListener.php) ## Reconciled Architecture @@ -141,9 +141,9 @@ in Paymenter core. For implementation-level detail, use these versioned repository guides: -- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/02-SERVICES.md) -- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/03-API.md) -- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/04-EVENTS.md) -- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/09-IMPLEMENTATION.md) -- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/DECISIONS.md) -- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/PROGRESS.md) +- [02-SERVICES.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/02-SERVICES.md) +- [03-API.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/03-API.md) +- [04-EVENTS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/04-EVENTS.md) +- [09-IMPLEMENTATION.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/09-IMPLEMENTATION.md) +- [DECISIONS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/DECISIONS.md) +- [PROGRESS.md](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/PROGRESS.md) diff --git a/.qoder/repowiki/en/content/Core Services/Core Services.md b/.qoder/repowiki/en/content/Core Services/Core Services.md index 2a849cd..53e2a4c 100644 --- a/.qoder/repowiki/en/content/Core Services/Core Services.md +++ b/.qoder/repowiki/en/content/Core Services/Core Services.md @@ -17,7 +17,7 @@ `SchedulerHealthService`, and the audit/configuration services provide the supporting policies and operator visibility. -[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/02-SERVICES.md) +[Current service guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/02-SERVICES.md) diff --git a/.qoder/repowiki/en/content/Deployment.md b/.qoder/repowiki/en/content/Deployment.md index 24d1ea6..ae6ec0e 100644 --- a/.qoder/repowiki/en/content/Deployment.md +++ b/.qoder/repowiki/en/content/Deployment.md @@ -27,7 +27,7 @@ by the cross-repository workflow. Before enabling dynamic stock: The API key and alert webhook migrations encrypt stored credentials. Customer errors remain generic; detailed upstream failures belong only in protected logs. -[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/09-IMPLEMENTATION.md) +[Current implementation checklist](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/09-IMPLEMENTATION.md) diff --git a/.qoder/repowiki/en/content/Event System.md b/.qoder/repowiki/en/content/Event System.md index 2d8172f..de39139 100644 --- a/.qoder/repowiki/en/content/Event System.md +++ b/.qoder/repowiki/en/content/Event System.md @@ -15,7 +15,7 @@ companion lifecycle. The reconciled extension does not register cleanup, reconciliation, capacity alerts, and scheduler-lag checks are registered from `DynamicPterodactyl::boot()`. -[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/04-EVENTS.md) +[Current event guide](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/04-EVENTS.md) diff --git a/.qoder/repowiki/en/content/Testing.md b/.qoder/repowiki/en/content/Testing.md index 272efc8..e87f684 100644 --- a/.qoder/repowiki/en/content/Testing.md +++ b/.qoder/repowiki/en/content/Testing.md @@ -14,14 +14,14 @@ process-private named-memory database and rejects inherited generated URIs in child processes. MySQL/MariaDB tests may use only the explicitly named `paymenter_test` database while `APP_ENV=testing`. -[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php) and -[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/TestDatabaseGuard.php) +[Test bootstrap](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/tests/bootstrap.php) and +[database guard](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/tests/TestDatabaseGuard.php) **Referenced Files in This Document** - [phpunit.xml](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml) -- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php) +- [tests/bootstrap.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/tests/bootstrap.php) - [tests/TestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php) - [tests/LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php) - [Services/ReservationService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php) @@ -86,7 +86,7 @@ U --> AC **Diagram sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) - [Services/ReservationService.php:1-453](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ReservationService.php#L1-L453) @@ -97,7 +97,7 @@ U --> AC **Section sources** - [phpunit.xml:1-43](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L1-L43) -- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php#L1-L21) +- [tests/bootstrap.php:1-21](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/tests/bootstrap.php#L1-L21) - [tests/TestCase.php:1-63](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/TestCase.php#L1-L63) - [tests/LaravelTestCase.php:1-183](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L1-L183) @@ -142,7 +142,7 @@ sequenceDiagram **Diagram sources** - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/tests/bootstrap.php#L23-L48) - [tests/LaravelTestCase.php:13-25](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php#L13-L25) ## Detailed Component Analysis @@ -361,7 +361,7 @@ Debugging tips: - Use assertDatabaseHas/assertDatabaseMissing to validate exact state changes in reservations and audit logs. **Section sources** -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/tests/bootstrap.php#L23-L48) - [tests/Unit/ResourceCalculationServiceTest.php:18-33](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ResourceCalculationServiceTest.php#L18-L33) - [tests/Unit/AlertServiceTest.php:26-62](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/AlertServiceTest.php#L26-L62) - [tests/Unit/ReservationServiceTest.php:29-46](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ReservationServiceTest.php#L29-L46) @@ -383,7 +383,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:13-20](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L13-L20) - [phpunit.xml:28-41](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L28-L41) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/tests/bootstrap.php#L23-L48) ### Writing New Tests - Unit tests: @@ -425,7 +425,7 @@ The test suite provides robust coverage across service logic, API endpoints, and **Section sources** - [phpunit.xml:34-36](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/phpunit.xml#L34-L36) -- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/8b95295e4911d2be9d865ff000dfd7313278c3ab/tests/bootstrap.php#L23-L48) +- [tests/bootstrap.php:23-48](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/fe20627c71984aef6676a21fc7445c4fa5a19911/tests/bootstrap.php#L23-L48) - [tests/Feature/ReservationApiTest.php:402-446](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/ReservationApiTest.php#L402-L446) ### Assertion Patterns diff --git a/.qoder/repowiki/en/meta/repowiki-metadata.json b/.qoder/repowiki/en/meta/repowiki-metadata.json index f629e25..e655dd3 100644 --- a/.qoder/repowiki/en/meta/repowiki-metadata.json +++ b/.qoder/repowiki/en/meta/repowiki-metadata.json @@ -1 +1 @@ -{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"18-36","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-18T06:47:36.678135+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"20-29","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-18T06:47:36.681054+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"31-45","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-18T06:47:36.6811344+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"13-45","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-18T06:47:36.681216+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"27-33","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-18T06:47:36.681269+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#223-264","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 223-264","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#20-29","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 20-29","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#27-33","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-33","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBW0kY68nN6yH347gACSKnGW/GaWsrfe1qmD5Vs4yiF9Bg4+cNg243x5/lrCPGe0ZLa727Kgt90Uf0qPTmGz2CCcagpDlxGuQ7KqPUQcnjLaS5faJVmqkBWfw6JX8uB8qtdCgeBozoNT8CS3Bl+VaFcrfo46PhuL+4MV4UlG69rB+KEYv2FlCDFDg9dsS+3XTkwBCvSqfvBNpmup+JH+w/q41CDiYfTbbURVO8q98JASJEHxb7rNSya1EFRu03Dndw5/hcunp6sW3i/mUBf3rxpXMRj7LhAAzagrVZYsK5LpuTLXislaMmRF+QNJZ+IT2lA/DQouhtUWc62leDrTc90zHDuF0e3jmfC8eu07DCVNzcVaikeY2HvQANYSq9rcpC9dzQDVFpKkVZPyhummuPO6U99ZLXQfwklIsKdCVTSZVinDVknwHBRxCYkuHbrR8PCWVfl3nrZOl4z3lC/mgPD7igYiJ64AUnOrpRNW3FBxgRf+8BvCrHeO/WIMVcJAbwWpx1XZdbGR+ktnHoWF73udn49QqG7nwtZCHkmejnF7RE14lQ8+LnaecPtPbDVehaKMSZUoX61sD47oraIoF5YU4E4zx2W6+7KWhB+NpL6ko1IG+UcHaD4hkEfJeD/2SeBD7vRpayej1ACgV5vne+TGzI7kZjsnKCjMqmxL4YD2RzBYMKD6LQL6+ubIXcmtFJAr/Qf1KdnxmlKveyXnZvX/ndj/g4n7iBoa+G06u5nlxnDftLOS1UX5Akt9Sa4ReIpPgc+Iu4fZiEvIogShhlx03pJAKPKeqY42rc4Hmh/zj2ffRkETYofbIvn6wCSpMGtQgaNCIsoTBzZqBh0tM7Ms2F9sOuNc6VOVytLWrAGs3Uj9mAw1cTz5V3dDkS8Iqc+2KwYHX1PPfXqBnFJ9XWfpzrzj1AUpLdt2Z96y1BKsDO8FeK7GHaIwMaAh0x3oc2MEQ48zBkemSFRqIbRb6rRjJaXwqbblx57l65FhBcMxFJxsPldnLySuNmXFfz1BkfSZ5DNpDxfbRaWAgJ5iptfMKdXbJy30ubNAJBkJhH4W4vLOQclfbDxGrO05ifqQbqraigV+gsHDqbEOiWWDQntcPu4du6DA+lClzPznkDuMn7ja/xjWhR8ohc2fY4GLWlOImAZLQEAyJmjJuZjDb+wqcLkwv/j9SeZbOJGELa6Y6Cr8itehW5lwWc5TsSfqavSxmD9CM2kCWNa9KxKdXaIxsUdn3AszUAdFlaPjG1P92QEIZMq5VR63US8SMFRS/lg2Bu/R10wr78W2ugpCg5hl4fZ5p/1vmKfSOK9ausuHQkeqqTABqn+iCT1Z7fU7QiEJ1KksgoDFkz8d4juqNhT7IjgBmnKpjlFLoMF070nLjTwO0MpA2l6ecAQhNFxkCTTgbwRAIdm91gS5JWtJnfYT+O23P17YXLCRKgLW9r5xM89j/ujErpG3/BIYXQkGGTGjTpO/lzd6VuHMlCDRwq73TZwT6AUgKKmb39ODafcEgXDC0Bwj49ZcUbc5EUw20RKYOccxNuKtBfilv6f7hbd8Hu0elrwUXFysMGHrQEIp5zXnFc3NBoJTtz5sGtxvwxy8KxeukwOhTloRknS/PinVWgDSl7tIsvU41/UPsEcjYzvczZ7nHfW+gpamwJoBNcYBOgGuCXoh+r/X+5NP4J0E8n/b2wCID44OPvacVG4V0qgjxQD4xvuliHGhoyte4iUvy5yOLrxbtwVmw5WBJUPAVwPgvGGRdqqVGnUW9k5T6rUGgAYhhHc5FTr9y4OibhX47uWd5eEv8IHnOhQT5/OyBAM1DOPcI1CQf0W6Pe/UObhm1662/8HXjlFAWsAJiyHi+I4iqPHBoOO9+l5Ng9s7uFUXtS6a2de/JIymAUP30+H8rrNsAGFKDIDiIVgJoPtOqSM+8eDo5CQvS/Wtf9VNIbJ0jbt8M9D79XxKedIjsFMGtgC4JPtycHOsQu3VsEvlFdhN60jr0Dd8w2Fa1hkc=","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"# Dynamic Pterodactyl Extension Overview\n\nDynamic Pterodactyl is a companion extension for Paymenter 1.5.7 and its built-in Pterodactyl provisioner. It adds server-owned complete-vector RAM, CPU, disk, and allocation quotes; deterministic node selection; durable checkout and upgrade commitments; capacity alerts; and operator diagnostics without exposing node identity to customers.\n\n## Current architecture\n\n- `PterodactylInventoryService` performs strict, paginated, fail-closed reads of locations, nodes, servers, and allocations.\n- `ResourceCalculationService` combines live inventory with local commitments and explicit per-node `NodeCapacityPolicy` records. Stock Pterodactyl does not supply CPU capacity.\n- Paymenter cart events create and cancel short-lived holds. Payment, provisioning, renewal, cancellation, and upgrade state are coordinated by the companion Paymenter lifecycle rather than public reservation endpoints or invoice/service-created listeners in this extension.\n- Paid commitments and allocation claims are durable and idempotent. Dynamic products fail closed on malformed, incomplete, duplicated, orphaned, or unavailable inventory.\n- The Pterodactyl application key and alert webhook URLs are encrypted at rest. Webhooks are restricted to revalidated public HTTPS endpoints with pinned DNS and no redirects or proxies.\n- Deployment remains paused until the exact extension and Paymenter companion commits are reviewed, merged, migrated, and a real-panel staging lifecycle canary passes.\n\n## Documentation status\n\n`Architecture Overview/Architecture Overview.md` is the canonical current guide. The other 41 Qoder pages are preserved historical snapshots with explicit banners so earlier documentation and source trails remain available without overriding the reconciled architecture.","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-18T06:44:22.5011777+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin/\\n│ ├── Pages/{AuditLogPage,Dashboard,NodeMonitoring,SetupWizard}.php\\n│ └── Resources/{AlertConfigResource,NodeCapacityPolicyResource,ReservationResource}.php\\n├── Events/AlertDeliveryFailed.php\\n├── Http/\\n│ ├── Controllers/Api/{AvailabilityController,ResourceQuoteController,UpgradeQuoteController}.php\\n│ ├── Controllers/Api/Admin/{AdminCapacityController,AdminReservationController}.php\\n│ └── Middleware/EnsureUserIsAdmin.php\\n├── Listeners/{CartItemCreatedListener,CartItemDeletedListener}.php\\n├── Models/\\n│ ├── {AlertConfig,AlertDeliveryLog,AuditLog,NodeCapacityPolicy,ResourceReservation}.php\\n│ └── durable provisioning and upgrade lifecycle models\\n├── Notifications/\\n├── Policies/ResourceReservationPolicy.php\\n├── Services/\\n│ ├── {PterodactylInventoryService,ResourceCalculationService,ResourceQuoteService}.php\\n│ ├── {ReservationService,ReservationConfigurationService,UpgradeReservationService}.php\\n│ ├── {NodeSelectionService,NodeCapacityPolicyService,ConfigOptionSetupService}.php\\n│ ├── {AlertService,WebhookEndpointPolicy,SchedulerHealthService}.php\\n│ └── lifecycle integrity, audit, and operator-alert services\\n├── database/migrations/ # 22 forward migrations\\n├── resources/views/admin/\\n├── routes/api.php\\n├── tests/{Feature,Unit}/\\n├── .github/workflows/cross-repository-integration.yml\\n├── AGENTS.md\\n├── CLAUDE.md\\n├── DECISIONS.md\\n├── PROGRESS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"8b95295e4911d2be9d865ff000dfd7313278c3ab","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-18T06:45:47.5747448+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"agent/rebase-pr22-on-pr23\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file +{"code_snippets":[{"id":"48b7ce6dca7d39b1c8c59d2019fecebd","path":"routes/api.php","line_range":"17-22","gmt_create":"2026-08-14T19:47:29.0866231+10:00","gmt_modified":"2026-08-14T19:47:29.0866231+10:00"},{"id":"63143fecd4df4183b3756587b465bb0b","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"18-36","gmt_create":"2026-08-14T19:47:29.0871327+10:00","gmt_modified":"2026-08-18T06:47:36.678135+10:00"},{"id":"221ebd0fd2828b2854f959575b99e1c3","path":"Services/NodeSelectionService.php","line_range":"78-97","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"d64732920886e90de00ee4624b3a7b09","path":"Services/ResourceCalculationService.php","line_range":"23-67","gmt_create":"2026-08-14T19:47:29.0876441+10:00","gmt_modified":"2026-08-14T19:47:29.0876441+10:00"},{"id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","path":"DECISIONS.md","line_range":"237-239","gmt_create":"2026-08-14T19:47:29.0913239+10:00","gmt_modified":"2026-08-14T19:47:29.0913239+10:00"},{"id":"84fd25e923e2751ef2c02b83ce548d94","path":"Services/ResourceCalculationService.php","line_range":"223-264","gmt_create":"2026-08-14T19:47:29.091849+10:00","gmt_modified":"2026-08-14T19:47:29.091849+10:00"},{"id":"223b6de577f16ce5ba3530942d7e659e","path":"routes/api.php","line_range":"32-40","gmt_create":"2026-08-14T19:47:29.0928897+10:00","gmt_modified":"2026-08-14T19:47:29.0928897+10:00"},{"id":"0d059535de46ca676e7d42e859e4d1d7","path":"Http/Middleware/EnsureUserIsAdmin.php","line_range":"9-21","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-14T19:47:29.093398+10:00"},{"id":"d73b585efdfd9612d3fdacb25c16a83c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"20-29","gmt_create":"2026-08-14T19:47:29.093398+10:00","gmt_modified":"2026-08-18T06:47:36.681054+10:00"},{"id":"ce8c6f628b7674134170b278e6498b95","path":"tests/Feature/AvailabilityApiTest.php","line_range":"31-45","gmt_create":"2026-08-14T19:47:29.0939215+10:00","gmt_modified":"2026-08-18T06:47:36.6811344+10:00"},{"id":"18599a3a741811129d02db625ec1a190","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"9-20","gmt_create":"2026-08-14T19:47:29.0944322+10:00","gmt_modified":"2026-08-14T19:47:29.0944322+10:00"},{"id":"6628dbaea27cd7799e76d0ff29784c51","path":"Services/NodeSelectionService.php","line_range":"5-12","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"0fcceacd3f4f7bd784c2498597b94cdd","path":"Services/ResourceCalculationService.php","line_range":"10-21","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-14T19:47:29.094954+10:00"},{"id":"120a44fe5780fed8b9e50178f2653f0c","path":"tests/Feature/AvailabilityApiTest.php","line_range":"13-45","gmt_create":"2026-08-14T19:47:29.094954+10:00","gmt_modified":"2026-08-18T06:47:36.681216+10:00"},{"id":"0c2729e6e2cbf5369a9d05fbf67a876d","path":"Http/Controllers/Api/AvailabilityController.php","line_range":"27-33","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-18T06:47:36.681269+10:00"},{"id":"8986b3d4eb9c79faeba772245af7f5ad","path":"Services/ResourceCalculationService.php","line_range":"487-631","gmt_create":"2026-08-14T19:47:29.096503+10:00","gmt_modified":"2026-08-14T19:47:29.096503+10:00"}],"knowledge_relations":[{"id":82,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"c673875c-4422-476d-ab2d-b9a260baa620","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:48:47.8160652+10:00","gmt_modified":"2026-08-14T18:48:47.8160652+10:00"},{"id":83,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"2970fe7b-6d2f-497f-9362-3e73a595927f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:48:47.8170983+10:00","gmt_modified":"2026-08-14T18:48:47.8170983+10:00"},{"id":84,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:48:47.8176101+10:00","gmt_modified":"2026-08-14T18:48:47.8176101+10:00"},{"id":85,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":86,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"52e74833-e71c-416c-abef-6a52d5e7d237","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:48:47.8181258+10:00","gmt_modified":"2026-08-14T18:48:47.8181258+10:00"},{"id":87,"source_id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","target_id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 24a7e201-6cbf-483a-aa9d-07769f8ab369 -> 05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":88,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:48:47.8186468+10:00","gmt_modified":"2026-08-14T18:48:47.8186468+10:00"},{"id":89,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:48:47.8191626+10:00","gmt_modified":"2026-08-14T18:48:47.8191626+10:00"},{"id":90,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":91,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:48:47.8196891+10:00","gmt_modified":"2026-08-14T18:48:47.8196891+10:00"},{"id":92,"source_id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","target_id":"397c6189-f7af-4992-b081-938fbeb2a16a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 752bcc4b-21c9-48f2-9375-e4a7d290edbf -> 397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":93,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> 9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:48:47.8202032+10:00","gmt_modified":"2026-08-14T18:48:47.8202032+10:00"},{"id":94,"source_id":"188acf53-87c9-4598-b284-fc851204c59f","target_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 188acf53-87c9-4598-b284-fc851204c59f -> f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":95,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":96,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"8ad6f733-a3db-49b6-a00c-339663ececfb","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:48:47.8207324+10:00","gmt_modified":"2026-08-14T18:48:47.8207324+10:00"},{"id":97,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":98,"source_id":"18e54911-5366-49c0-8103-29d10e4e011f","target_id":"6b790301-e99f-4c01-abc6-c1d2251b04da","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 18e54911-5366-49c0-8103-29d10e4e011f -> 6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:48:47.8213183+10:00","gmt_modified":"2026-08-14T18:48:47.8213183+10:00"},{"id":100,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":101,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:48:47.8223634+10:00","gmt_modified":"2026-08-14T18:48:47.8223634+10:00"},{"id":102,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:48:47.822921+10:00","gmt_modified":"2026-08-14T18:48:47.822921+10:00"},{"id":103,"source_id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","target_id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: f70303b7-4f5e-4d4c-a3cd-920ef1064fd7 -> 5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":104,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":105,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:48:47.8234353+10:00","gmt_modified":"2026-08-14T18:48:47.8234353+10:00"},{"id":106,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"e02882bb-0384-4cdb-84f8-774469b89c09","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":107,"source_id":"6037ff6d-e047-45ad-a568-3493aa4a5351","target_id":"0db89115-1be8-40f6-a930-ca751cc20e05","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 6037ff6d-e047-45ad-a568-3493aa4a5351 -> 0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:47.823947+10:00","gmt_modified":"2026-08-14T18:48:47.823947+10:00"},{"id":108,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"f39634e8-6feb-40fc-9768-344eb9186ee9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:48:47.8244627+10:00","gmt_modified":"2026-08-14T18:48:47.8244627+10:00"},{"id":109,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"a5435748-2119-4c51-be75-2fd8ff52c01a","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":110,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":111,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"ccb27e95-0867-425f-b0d9-148c2a46646e","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:47.8250114+10:00","gmt_modified":"2026-08-14T18:48:47.8250114+10:00"},{"id":112,"source_id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","target_id":"84c24e35-8404-439b-ae58-deb60a3a485b","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 3c632a4e-8679-49dc-82c7-17ae7c52c2d8 -> 84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.8255381+10:00","gmt_modified":"2026-08-14T18:48:47.8255381+10:00"},{"id":119,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"92fd52c4935466c2b4907fed01ad2589","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: routes/api.php","gmt_create":"2026-08-14T19:47:29.0970744+10:00","gmt_modified":"2026-08-14T19:47:29.0970744+10:00"},{"id":120,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6227d1ffcd3afe1f45278e49f79ec4ba","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":121,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"246f3c22dae73dc96be95625fd366ebf","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":122,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d4ac1e9bd132b778065ce759f5c1fe18","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Services/ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0975865+10:00","gmt_modified":"2026-08-14T19:47:29.0975865+10:00"},{"id":123,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"2881ef2b7fc68234fed9616f7677d1f5","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: Http/Middleware/EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":124,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"00371db7438a3659399cd6adba728d8c","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: tests/Feature/AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0981107+10:00","gmt_modified":"2026-08-14T19:47:29.0981107+10:00"},{"id":125,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"70994fc8e7bbb62d03a93e49ef3b0f98","source_type":"WIKI_ITEM","target_type":"SOURCE_FILE","relationship_type":"REFERENCED_BY","extra":"Wiki references source file: DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":126,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#17-22","gmt_create":"2026-08-14T19:47:29.0986221+10:00","gmt_modified":"2026-08-14T19:47:29.0986221+10:00"},{"id":127,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"48b7ce6dca7d39b1c8c59d2019fecebd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 17-22","gmt_create":"2026-08-14T19:47:29.0991483+10:00","gmt_modified":"2026-08-14T19:47:29.0991483+10:00"},{"id":128,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":129,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"63143fecd4df4183b3756587b465bb0b","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 18-36","gmt_create":"2026-08-14T19:47:29.0996604+10:00","gmt_modified":"2026-08-14T19:47:29.0996604+10:00"},{"id":130,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":131,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"221ebd0fd2828b2854f959575b99e1c3","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 78-97","gmt_create":"2026-08-14T19:47:29.1001759+10:00","gmt_modified":"2026-08-14T19:47:29.1001759+10:00"},{"id":132,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#23-67","gmt_create":"2026-08-14T19:47:29.1006846+10:00","gmt_modified":"2026-08-14T19:47:29.1006846+10:00"},{"id":133,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"d64732920886e90de00ee4624b3a7b09","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 23-67","gmt_create":"2026-08-14T19:47:29.1012052+10:00","gmt_modified":"2026-08-14T19:47:29.1012052+10:00"},{"id":134,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: DECISIONS.md#237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":135,"source_id":"70994fc8e7bbb62d03a93e49ef3b0f98","target_id":"7f4ef7b0b87e643be1b3bb62f36d0e3e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 237-239","gmt_create":"2026-08-14T19:47:29.1043215+10:00","gmt_modified":"2026-08-14T19:47:29.1043215+10:00"},{"id":136,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#223-264","gmt_create":"2026-08-14T19:47:29.1048318+10:00","gmt_modified":"2026-08-14T19:47:29.1048318+10:00"},{"id":137,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"84fd25e923e2751ef2c02b83ce548d94","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 223-264","gmt_create":"2026-08-14T19:47:29.1053538+10:00","gmt_modified":"2026-08-14T19:47:29.1053538+10:00"},{"id":138,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: routes/api.php#32-40","gmt_create":"2026-08-14T19:47:29.1063864+10:00","gmt_modified":"2026-08-14T19:47:29.1063864+10:00"},{"id":139,"source_id":"92fd52c4935466c2b4907fed01ad2589","target_id":"223b6de577f16ce5ba3530942d7e659e","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 32-40","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":140,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Middleware/EnsureUserIsAdmin.php#9-21","gmt_create":"2026-08-14T19:47:29.1069583+10:00","gmt_modified":"2026-08-14T19:47:29.1069583+10:00"},{"id":141,"source_id":"2881ef2b7fc68234fed9616f7677d1f5","target_id":"0d059535de46ca676e7d42e859e4d1d7","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-21","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":142,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#20-29","gmt_create":"2026-08-14T19:47:29.1074729+10:00","gmt_modified":"2026-08-14T19:47:29.1074729+10:00"},{"id":143,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"d73b585efdfd9612d3fdacb25c16a83c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 20-29","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":144,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":145,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"ce8c6f628b7674134170b278e6498b95","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 31-45","gmt_create":"2026-08-14T19:47:29.1079857+10:00","gmt_modified":"2026-08-14T19:47:29.1079857+10:00"},{"id":146,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"18599a3a741811129d02db625ec1a190","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#9-20","gmt_create":"2026-08-14T19:47:29.1090515+10:00","gmt_modified":"2026-08-14T19:47:29.1090515+10:00"},{"id":147,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"18599a3a741811129d02db625ec1a190","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 9-20","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":148,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/NodeSelectionService.php#5-12","gmt_create":"2026-08-14T19:47:29.1095851+10:00","gmt_modified":"2026-08-14T19:47:29.1095851+10:00"},{"id":149,"source_id":"246f3c22dae73dc96be95625fd366ebf","target_id":"6628dbaea27cd7799e76d0ff29784c51","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 5-12","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":150,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#10-21","gmt_create":"2026-08-14T19:47:29.1101013+10:00","gmt_modified":"2026-08-14T19:47:29.1101013+10:00"},{"id":151,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"0fcceacd3f4f7bd784c2498597b94cdd","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 10-21","gmt_create":"2026-08-14T19:47:29.1106279+10:00","gmt_modified":"2026-08-14T19:47:29.1106279+10:00"},{"id":152,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: tests/Feature/AvailabilityApiTest.php#13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":153,"source_id":"00371db7438a3659399cd6adba728d8c","target_id":"120a44fe5780fed8b9e50178f2653f0c","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 13-45","gmt_create":"2026-08-14T19:47:29.1111413+10:00","gmt_modified":"2026-08-14T19:47:29.1111413+10:00"},{"id":154,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Http/Controllers/Api/AvailabilityController.php#27-33","gmt_create":"2026-08-14T19:47:29.112188+10:00","gmt_modified":"2026-08-14T19:47:29.112188+10:00"},{"id":155,"source_id":"6227d1ffcd3afe1f45278e49f79ec4ba","target_id":"0c2729e6e2cbf5369a9d05fbf67a876d","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 27-33","gmt_create":"2026-08-14T19:47:29.1127093+10:00","gmt_modified":"2026-08-14T19:47:29.1127093+10:00"},{"id":156,"source_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"WIKI_ITEM","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Wiki contains code snippet: Services/ResourceCalculationService.php#487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":157,"source_id":"d4ac1e9bd132b778065ce759f5c1fe18","target_id":"8986b3d4eb9c79faeba772245af7f5ad","source_type":"SOURCE_FILE","target_type":"CODE_SNIPPET","relationship_type":"CONTAINS","extra":"Source file contains code snippet: 487-631","gmt_create":"2026-08-14T19:47:29.1132187+10:00","gmt_modified":"2026-08-14T19:47:29.1132187+10:00"},{"id":158,"source_id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","target_id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","source_type":"WIKI_ITEM","target_type":"WIKI_ITEM","relationship_type":"PARENT_CHILD","extra":"Wiki parent-child relationship: 9573fec1-f465-4fe6-8c91-0bb4bba9d247 -> 4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T19:47:29.6736745+10:00","gmt_modified":"2026-08-14T19:47:29.6736745+10:00"}],"source_files":[{"id":"92fd52c4935466c2b4907fed01ad2589","path":"routes/api.php","filename":"api.php","gmt_create":"2026-08-14T19:47:29.0800247+10:00","gmt_modified":"2026-08-14T19:47:29.0800247+10:00"},{"id":"6227d1ffcd3afe1f45278e49f79ec4ba","path":"Http/Controllers/Api/AvailabilityController.php","filename":"AvailabilityController.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"246f3c22dae73dc96be95625fd366ebf","path":"Services/NodeSelectionService.php","filename":"NodeSelectionService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"d4ac1e9bd132b778065ce759f5c1fe18","path":"Services/ResourceCalculationService.php","filename":"ResourceCalculationService.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"2881ef2b7fc68234fed9616f7677d1f5","path":"Http/Middleware/EnsureUserIsAdmin.php","filename":"EnsureUserIsAdmin.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"00371db7438a3659399cd6adba728d8c","path":"tests/Feature/AvailabilityApiTest.php","filename":"AvailabilityApiTest.php","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"},{"id":"70994fc8e7bbb62d03a93e49ef3b0f98","path":"DECISIONS.md","filename":"DECISIONS.md","gmt_create":"2026-08-14T19:47:29.0860903+10:00","gmt_modified":"2026-08-14T19:47:29.0860903+10:00"}],"wiki_catalogs":[{"id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Getting Started","description":"getting-started","prompt":"Create comprehensive getting started content for the Dynamic Pterodactyl extension. Explain what this companion extension does - adding dynamic resource sliders (RAM/CPU/Disk) to Pterodactyl products with real-time availability checking and 15-minute reservations. Document installation steps within Paymenter, basic configuration of Pterodactyl API credentials, and initial setup process. Include quick start examples showing how to configure dynamic slider options in products and verify the extension is working. Provide troubleshooting tips for common setup issues and explain the relationship between this extension and Paymenter's built-in Pterodactyl server extension.","progress_status":"completed","dependent_files":"README.md,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:29:54.6189588+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00","raw_data":"WikiEncrypted:qfgbutC7oyxR6nMxrwk1ODnNMBEQ3/sG78fQT1yXWjspqw7wFsgcSykO0UmGZY8QTKN7XNoRj5gLcQItLpCOKXutiG+6VCjcMYiCHQKLTKFKR0Qro1TzWeUG0MgAHCXo/VO92qWUk+WvITJEKK9q1DB85tBLvLFKQ1XDWbKutFvv8WSiZ7tnW/i6ZfMblJ4o5FA056HZiRAzyS/GmVJRNKSiJw7FKn3J0ypU+hyhD2JArjvJ1bDmDDKTdL+4G/oidN4gZMbRsGB8tqNkthZavuwzo4pEIzA8golXB4LnDRXnuig5o0aYse/6dhFu3oCOPlnGqWh+zfVHfVqrnzxXgjCdtVMGTobC94rMeKY/NClSuUQ/Po6njlkdgyhIibM0quRS3rxLorr39hHBon2WY2z4aZ2rXwC0UJpQDAgoYgQO9Cy1vzRMdQyeN7w6eQ53WuNWtEQPgSGzdxw3ejDCr11BAY/Duo9/WgRW7qAJniVNf73Cn7lrOJY2QmoGeBQhojD1YTYOSu9P4qDpbJ/TUfdhMXj/wETq61329gGQBgVBqiKlUyzZWOc5GXcyZCPkDrRvKKg7SJHxoL9MzN/7vk2OK/1Bp4OSWzbAAlQeD2Wbf9JSxHiqG82dUGhbP3s57o5T3vUDy9bVxIwo1EAVJ+jkAQ+R2R0OwN0XcwnrMBmFzlE8+j1yM/oMF01PZMk/W+CclXdr20OOL72KxV3ySMGk0kPu3gZbP5fP5Pmz4MSvg3s4zhooMHZRvPQB5q83NtSat9TvhIJcTNjrUn7JDtOYeiCQxXvn8D+DtuZjsW0udKFkwTQjzIjlLeb0F1P4Hu34fznKYvg7RBw22vrkrwQ8RJ7jpm1OZC4DoGGV+gKjf/goH4hpp1y8romzxgpd5BAplcA3Kz5zsX+vAv7g3xIuNFFLKM+tDS98jxvEVqhC67THO9QbmdpNMFgBSDaBeZgra84ACzmpB6y+ANSMU4HC0v82daUwc4SnwY2MxfUfyQP41+WoEtNoSuu584vKWVIoIsYYI4BQKv1+518jlPpXW9wN7gVhsbgnvhTSmhGpfbRN6PlY8vMGz/rBwyRr/sUMatYdwMt4mdU2iy9UcjfxPL+sqEhGscQeqkSoHKcNHvYYUQZSNxoBrGz0DMjecwsWeDc2CEHMc0exxGeOLKr8LaPYsGm3vloR6oCK7FQSZXkDQuJRe3Clg7yBDwFOQQ8vWxQDOflaFqGODyH/p3BpS7ncjX5CU3Iy/r/WlRx0OkOLgjzLQgq0EDepi7L7yEf2Gc1tG3hIeh5ijcZtClg3foiYgv5oMl/G8nKRj/a6mbbQd3ywZF4ujZg6AzJXIoaKF/qnZOo0mrwCrJdctIBHfCquUNEYQmosqbpjKCuhheKvfl5hQrLTczSAuxmuzO/Yc/Dz38Jb5h3Lyr1AQQ=="},{"id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Public API Endpoints","description":"public-api","prompt":"Create comprehensive API documentation for all public endpoints exposed by the Dynamic Pterodactyl extension. Document availability checking endpoints that return aggregate location-based capacity data, pricing calculation endpoints that delegate to Paymenter core, and reservation management endpoints for checkout flow integration. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using web session with auth middleware, and rate limiting (30 req/min for availability/pricing, 10 req/min for reservations). Provide concrete request/response examples showing how customers can check resource availability, calculate dynamic pricing, create temporary reservations during checkout, and manage their reservation lifecycle. Document security considerations including why node-level details are never exposed to customers and only aggregate per-location maxima are returned.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00","raw_data":"WikiEncrypted:ooagOerKncaxKL5b9oe652R7gDvFSR3kpl9W+Fadq9Uz5Mnp8ZiIexHuG1yXixmdt+TYeArNR3pATyYGiWkJSW3cnnHVVaBLqw1/DAZctfZz5SrrnKfXDB1g6du4oEQQSdyIl+5RBfkgGcKji411VbhY7wR8A2PCz2QWblB9g8cAYgJ691zqJMcNa2KHRFa+UABcu6mQ0WKKMfaN69GL7SVyGIaoEuDjBrq4wA10K4zPCifa8wAbcWwLgBuPasgR4jeOjpFKEaUttlLykKxg+Vo9irZPjKJUsDHNPR7MIWBhvlCYDfNUpX4Jj8e34fAkP4Nu8tIMZq4d9NF9cbMjkNl8uxR/GR2CBwIRZ/zRJfxGTrbqyvZZQpKvoADSbqDuzZBwSg7DOV42pdPYIx5Xo2fHNfcsCwxYCOXqfp7DqEJHMD8iJL4+DIq/pDcJxm27SlgU1F0KGaPFEyrf5OfaLqgrSW2TraYyqVcsiuDTL9SXctNAgumXDmg78YiSTpsV72uUlBt0FPxW4JBCIkk+BjBmcW8RtdXUCMAJ7pg2gp2CruLMKNGo86KA1mIWa68zx9fEmqGEaD7ipdTR3PrT5qKNUpEkx7AWGgF/glJ8EQYOgGbYBIAB3XuDUipElaIO92USro64v655HheuQko3XLspemMc2MxCKZTSxrXKafkGEWizRQAGsupq4iaLPKkkIliGMnBsYaIAywiuzoylFtqf5RrtuHm8wvb6j7oO44noUGuaCAz1rT7n72Enz3/eihpUzHGKZrbrZffdrkMfVCQlot3ZapDPKtE3dyMTnYX12GQGLwwEa9nVR9/wjomV4iVqAk4A8BihZ/4mp+1g2YnTdThd/mgkxrLOAOzopJjKgTE897rapVr30BXC1oLnSpcLtxVqZgEAKupPZdmeHy8tNB9+wF5fP39I2tB12xakNHFeTn8ICPRcOFT6iuOVl8+LwuWLPPJhBZz2G80SOniV2uWG/g4eUW67jy7rkwaT+qKeU1ZBs+fz4tmAiXCktSPT0V3H7BkqiXEktuFr8ozEe2rObfKNDw0ZhFfWWNoISHL40ELKgMsT53eB8tmQ2nS3hDu4Xt0rrOGqOxjSUiBAa6N2Lyijnz2Tob8PV2jHoNXHFSXHQhBOPIrFVPvTDH7VpXWLOaA+Mdg+s5wId1PsEqXY0kmV8yBG3yZP6sFo/4ZPdT+4pbSLV1XtpDb8ksCaQkOYik9MmG5zmrdYzPUDEaYoZxQTmpqDVYdMmaFivrolNg44OMJlodThspJu3kbgMrU+eSBEXkBzw+CsjkAUtAB9SCxTLseN/w2MmB86C/7Nar3QvdwbbeJQiHEZsxVoOwUFtXZufIzfpHGSktnGWNkh6zQsfSOAQj3a1tQlDJXYZMoelLWf1uEVSXggucBJqCG0g2XG1BnV5qxe21pAgPFEOCqZHJHSioUiuOOYgVmY7jtRyiVoJN4xovRNMPiU9Qcjk32CQHAWia1ExEpkehtyJ9hpwbk2ewiBvb5kdjCGrLGF/6OdkH4wM9GzY65u2BqKSFjuXkisQXl5fnMSL3cOKra+GlSAcyysPiQqsPase36Xqioe3m9OztWKKRQ/yvkAjmyU8b6ZXZ05FC2sAytRcimz7MG1dcaDcPUlIj8fQHVYSM8eLojVmQ9zb0eNvHpBUJEN7xk5KH1pR48JYe6pwHq0ygj5jJVsJ2uyq88bZNmUQfvskLnq0Zm8rR6J9JL1uEr/wa83N9vtuPVufq+ZRVjjC+uAkdoua6k3pwjkSPhox5Xz+hXuLD/J52SXj2Swd/AH6S+5r/Q4NyZPu1m8PcQ6lu6tmWbyBif0l7p8cua37wbIYu/WQdsQvpIOkfXUjoeEJ8e0tGjKQEOd+/ae68BMPiiq799roEfay6CGkNFEU4O45+A9suj3","layer_level":1},{"id":"e3386639-745b-4c62-9148-1ee933d1e0b6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Companion Extension Pattern","description":"companion-extension-pattern","prompt":"Create comprehensive content for the companion extension pattern used by Dynamic Pterodactyl. Explain how this extension integrates with Paymenter's existing Pterodactyl server extension rather than replacing it, maintaining separation of concerns while enhancing functionality. Document the extension lifecycle including installation, boot process, and configuration management. Detail how the extension hooks into Paymenter's core system through the Extension base class, manages its own database migrations, and registers custom routes and event listeners. Include examples of how the extension coexists with Paymenter's native pricing engine and service management without interfering with core functionality.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","progress_status":"completed","dependent_files":"DynamicPterodactyl.php,README.md","gmt_create":"2026-08-14T18:30:08.2198258+10:00","gmt_modified":"2026-08-14T18:37:13.2582594+10:00","raw_data":"WikiEncrypted:GiFMFkkXJ+CpqHtjlJI0P5zDw+fIYD9Q8TIJn5YTDPt1Cnff/j7r2yNL1IhqyfgJO6gHU3XwP2ukGvalSTvMuAD6r2jpOWfTyDg+RdVhX4r9J5/SleRUgd5FFLRPL/R8nNA1iOAqXibPENbSeJYVjvax/OqdOQmCVbRD9HswUeHN+0tgtLKDn306sLGfxgFDn3o0hDvmONYAFGIpXgOqTnPnFGzxnRnDOyAb1QA9ViOy+RUbyXiMbWZv1Sr9a0Xl5uV9sP0D4N0Iz7XiqIJmZlRpqgiOAVd/C54T2H0fUIop7jMpELsuatfjtD4o/n8qGTv6qO2Yhmtwq51WFOT43FQ2UshCVSIVeD4G4sg66VOSdSobnyXLXy4FdeJJeJFddOF4VnoAEHsKXkb44/+IBAvvg7MD8+1C3VQhFAZKo1f6UTEAUOuPZMkTxgjWEM9o9M26pGKcyr1UHk9EA71vmNBNjwuBtzmx73v2up/PjobfM8QQxk0ELjQPgUh1arrsuasAKPM2c9ck2kEh6mnpqBzexh7SFnANzb0R9tVthfU6wOTcI0BJKIoY+z+LtQBzuaA7VaLFRuSz1EsCwmY7Yqy3pJfipmVIAronNve4GaEnWwIAohLtWP9lnlv/dIdTJPDW5w02Vzmb6a2fDEGORlNxFDaoZLOs3bswbcgoCHnh8bOn21QfWbU2m7zcKHw6nrL+hYxEeC/OFJF9PjYw3Acj1Ounr8kzPW65oTtjhV2rFPh4f7080crNXvxY1ze0verbRcEJqgxoxRQibM3QsbhwFHN1xXL/gUJ9rTBVUWfCuzMY31+BR/BwxQVMJAEp7x0Okdt2BiuPKrM75Vn+wEms5Hf9U0ecHMvgN5T/tFfgynBxh3Hw+6DczHqIzNu5H4oMfMzrQUkJc4/u5Q17cIf7FOJyxbVanfYjnd4+RT3NMA0/5bLYPYEWpO1Su0COEAB858GOH0ihwIv/tmRT5KY7A/DE2CjqlRDJ5YyCg3urOcMPy2hL7bNrqYB2OGG/BRdQCqQVDlxxsna6bOs/OtLk780DGB4JBofks4wvZ1RxF8XDSOqbzl6GpbmJSXlhTmU4PDqqXwGCYOcThVh7lK6NhvQUae+ePDnXqktcQhplfW0U/jG8aWdw8mJ0+psdwkpoz7KXI0Mdnx7sWPlSutdjNV944A+weaO7WvkG8J2lCmuoUcdK8yklrFuSadv9D+UgzNV1pJxjwHYjamOfe8hbeoOCHVd+T6BdT/4jCxHwDuozTvS6lS3VnyVOF76BsgRZjQ0K6CnOGIk4xRZf0UWqtQ0zWOQTgpLxib1xQojDxGpLadIvmGu8KqsIZbdGuqgpp9YyYLxLDskTPUQJ6k2D/EDoa0YMGeVjGwL1ELj8DnfxBkIsa0mt0dE4pLxT8dpT+0AH80tTu1d9KmASWzJsT9AV6bTHHMYHE+9Z3RLXE6NoBa+aRA0X76uS5I9G","layer_level":1},{"id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ResourceCalculationService","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService, which handles real-time Pterodactyl API integration and availability calculations. Detail its core responsibilities including fetching location data, calculating node availability, building cluster snapshots, and managing pending reservations. Document key methods like getLocationAvailability(), buildClusterSnapshot(), verifyAvailability(), and testConnection() with their parameters, return values, and error handling patterns. Explain the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how it integrates with the reservation system to prevent overselling. Include examples of usage patterns, connection timeout handling, rate limit management, and degraded mode fallbacks when Pterodactyl is unavailable.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyH/jzXrNtu0OPy32NWRIx2SErsPsfwEjTq86GobRN8vNhs/nAvQEonb/+6iOxr91WVqfd0+8rlhIonNa1lSF8fObQ4f0/Sw4uGMBSx4WpewL6XpgpsGm8C6vV+Q4rxzL4+b+7xTDxZbb6TZXaLUyGcBwNm9BTkJZWzbJYNiHpdXPAX0h5gzXRSU4/zkNX/X/EezBMQrWT15z0ElAAkuyXuuZOA2M89a7w1uUXrNirY/4sh7VQw1DKz6O9o9l6/3t7LSMgLHyhSoPp4Mzmao3K+8r9qJbd1K4Kss4lowX8fe/OglUNRnKBZnrqGDfOzC94KCfdRlM3MRSoyF0AEw5xzCr6fkBpMCMCX4VFPhlgnpPSwz/eEgXvdUYm4O21HFRfPt1gbuR4nBIJvYFxy7ggS+xvIAoI72T/nEEzfKOBzrWIfv8WQMuY+Ud5Y2UnvWpygJ8IgVZx20RKPqw8aXIoP5wvrVPi/CTM/KbaInuTOKMgKMcvyrbtp65vkUv41TYVVdF7+2QeD068hp4ZEWZAqkK81DjQKv17mzl6nPy1PoPTPOBai5zamLM0i/NfswpW3lSjDr0jisQtqbb5jwzGN9UZmOtOBzu0PiN1f1SwLC3Jgwpf8LOTCN37s0FGD0rYCEUc6NS9I9naZt93/ehw4wB2JBhtZQcSCGwxvR3fFMWQTH5tYxcQ10ZTRT/9U4P6HLVJL9AempgocMQt2RswkzgUlgVTR4FNVCefZV/YkKhXgNz0xH4dG/vERqhqeeSQ80wcn2gKjl+lSjH7cfBmC8vUiEHaQz/to+xEzsY9apY/xuJL9/tI7+TX4CS7EF/Aqu1DIGCak0A5FZWLumaRKSzXKnxeDkkvZKazlSoKKmPmLQ0Nuj/oSx0GAG4Ke2GqA2t4HCAEyKX0WyS6lr08ooG1skak32NGuI/4v0dSbs5RrME4i5cy1p2Fzt9Rv7cTDDxhiYNwsZD+cKLgRIj9W/0uyh3lFloEVMRKT0YKbHBcJnGciJCEFoXLYcyT05htg9bZM1y0fHnASZ394Hkt+SwLD0cafIpqPHEgj1wCH2VQ+M4VB3YquUdyMcrGfBKPEOrQ59BzjtP52ZpW+nZt78Y0cTnKorJXwxSZ0DAJDC7dyk9VSMKu6Ms84iv6oK7Q3s87cbWpjJi5ne/P8Lr/uf0GKOLCpGhkroIhXfevzW7pzNLa1j7v1ZzxMzmHPj3u9FrVp+9lNqayYJJTQtSeYHeNMJ+Co6vhs+0ULxHJOVz+jUCWgRiMhNc5dr9OalYATUk/C+94dELvIa0LmhzJ2a2p6ycIVs1YIwXfZqzm+YDa60pt66v4N6UeR8Gk/FGl6wkENL70J6PiP0Iin5LMk+AFfUtheVbmVn9CU16tmPCdacuAxYGbdnyCrneAlSTZmV/aQc/GDtmZsPsCI8sb/k6BtQdRX+YdbKg0bnsiB75pTPx+GhdqLrmJoeT0fl/lCCKWdp+5OIF9E0ho3jg5TiPhwVKkQ7Ge7I6Q+o+TJb8ZlW4gCyLAQpgYRv7PQNKGo5FqbKyl8otr9XC/5AJ5Uz/qsV0yYE1fOqqh2aT7lS82YP6MBsLmH2SJSKWAGA/scRwEp/mjaEoFdXFaKuI2DdCJjRJJghcTlCxWdxoeBzJEMHKy4ydjUmU2shw0WyjK","layer_level":1},{"id":"52295bf9-bad3-435f-beac-e59e3eb28421","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Availability Endpoints","description":"availability-endpoints","prompt":"Create detailed API documentation for availability endpoints that return aggregate location-based capacity data. Document the GET /api/dynamic-pterodactyl/availability/{locationId} endpoint including required path parameters, authentication requirements (web session with auth middleware), and rate limiting (30 req/min). Provide comprehensive request/response examples showing how customers can check resource availability for a specific location. Document the response schema including total RAM, CPU, Disk availability, and per-node breakdowns. Explain why node-level details are never exposed to customers and only aggregate per-location maxima are returned. Include error handling for invalid locations, Pterodactyl API failures, and network timeouts. Address performance considerations including batched API calls to Pterodactyl and real-time data fetching without caching.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","progress_status":"completed","dependent_files":"tests/Feature/AvailabilityApiTest.php,Http/Controllers/Api/AvailabilityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00","raw_data":"WikiEncrypted:4zIDF+aXRMvw491krmgVvPuFfz47JZsP41ti+yqcjKh+lPAlT3jL1VT05V3PYVqNwDOoqBuKVup4l0s+swMAYUwXuUuQp1rfsZpJgObUAgVYM3caE5pf/YX4+bgtclgoD+8rpepWqf8tX+cgt3Pqpd8mUkimPHLITXzaus/y95xnPLeK6SEeZRD/6GgmBMvAVTWQA4ks8iB30aHxxf0bzsl6Kht6s6RVRO72uUYmzW+cpcSlzRP7rPkqc9Po2vxScn2B747Ew1EwxKYId25/JVF/brq+V52eKzrCTDySLCiP9MaVN5r8SjJb1gv0DWwyIwbNVSMf/hjnnNX17NYNYEVSSRpxYdSkDgHbE9E7ObaaUJ9I8bUPkqnl/ZamKtPuqLkdkj1rTCca1GOSZ5ynrak6G9Y8BZofL+C+qfmwB0qCgxZPXc0AR4nbIQrIdyVojBGeuY6zNAO1bggOURjOBDy5wZG2ITu91zMViOAOHE5bSNFk025EF1VurdGMhFQjcqK2aO+su1Ii9UKPQxOgMKdv8S2nvmFnWb4KNkCzjFtLmzxgb4gsFJqzf0bEyN1mZ/y/tuVqOspJ1Hd5DH3zkzRFxHSObF5EDg89gYnl6M9kqQnR42KEPO8PHaHC8Hi5n4CumW5pUr1G0aYSMPoEIjK2r8RlRGyVI/l+Zug4ivyvXxqpyPGHyflRkH5BqqTj3YND1uTFASi7DiDf5H2KF5kkG9SIOXyv33n+ahHPa8rIdy+VUFmxSgl3uyZtJpHbkaxeILiKbtoib0LvV/Ur+R/2QptMibKEAcGWCdF4u1y44yCztm0l3vnMR+7pCHUVrhC57JR6AIQOjtAPs+nOyUwiO9ebyTBvg5Ye2jyinKt7DMNJYynHxxE+Bpn0Pqoy8QIEJNr7LuovuEU7iMJiEBBa2Ej9YZoOFRc6VOrMX1aZ8qp8tb7yZhvE9uLGkwWBYKGbv/1t8obi5Jpwt6cgwBrW65h/DITO6+o6EtRAYla0KGERRGfMb6RJhOJGM9UPiN9YurhooSg5Cm5mldflVhcCnapalZ4YVfqbJnUaXOy1h/BjdSBX92oq2JobXQdcCGaUrak7OyezgWg1PdIdT7TychGIVn0HD/28xS/OBYXPIgUiWWQ2oOI4c26gzORBDqd8B2aSzPPpRMehbpbX15Cgvd5nXenjTUApPij3fTue1CwoF/POH4fkypVWoo096F34y/HPa6Ou73gNSuM8UJovXiKTBJJewKmTqF/as+6fYozzABaduvvf9/OV4jE7Xrpop0DaNrqMDtHdWVQx/o2d5OzMUFiiJfgYxzg9P/PGHl3nE6Rv6WgErRk0lOV4XZ9y//no/kYar4EdiPC6e6/gLgwqFgHsWNJYnxM6JyCvWI5K4GQfA1ZjFeg5s88Etr8GTe3LXgQ+NKJZSJFjCfYWJiQSu2a43zcNozbE6hkbZJHwNVBYo+q0wbBgmWBPUTDEJrajEdDbGvyn0JzA+yUby5NRUFslkv20yWJh1gGF31t1NLNmt4UTptxXo1mSgfJ0E5uqlFu1D1qsAkJ3p2lmhWhX4M/wn+UOfyuIHGEipYmm08PE3iNQEy3++IyebcuEl5iQtDuifu6QrDdawg+7bcxD088NEv5TQDWmHpQ5FmZl9AprXWjUP/o8QmL4ieok218GpGA8ynpbUZJw8wBDadkgFKtH96E78WkNrb/ZzWwVQ//OcWWdHrryjVWNcv840QqBuEHFsgqxHpuxj5yr8LIgbtaVUeBhPDSbjH0MX3QM/Mqi0ZO51e1KMtnx","layer_level":2},{"id":"366e7e10-0359-4523-8ce2-a28bf6870f63","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Reservations Table","description":"resource-reservations","prompt":"Create comprehensive data model documentation for the resource reservations table. Detail the complete schema including token-based tracking, cart item and service relationships, user associations, and Pterodactyl node/location references. Document all field definitions with their data types, constraints, and business purposes - particularly memory (MB), disk (MB), CPU (percentage), pricing snapshots, and status transitions. Explain the reservation lifecycle from pending to confirmed/expired/cancelled states, TTL expiration handling, and admin notes functionality. Include index strategies for efficient queries on node_id/status/expires_at combinations, foreign key relationships to cart_items, services, and users tables. Provide examples of common query patterns, status transition logic, and performance considerations for large reservation datasets.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,Models/ResourceReservation.php","gmt_create":"2026-08-14T18:30:21.2677394+10:00","gmt_modified":"2026-08-14T18:37:33.4304848+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz7yWP3UWe5rcj4mC/6a3Uf/FVHHmJPRh5nLy2qjVectWVxWLOLG0M7SDidCUWeuAs1OeYSDHfZV3e2GZ78DLy5mCUFtTHVFsxRpKNT0Qk4aw+8WBOpvoBxYxgnfg/4hbck7zuqmZi1lM2VizvRd4OeijyrVfNqEBDMT1ENE8Yxapht2awzLwKeAusNG2BCQ5zVycKhjbscq8HjlFZ925ppAjlrisBIkfy17wVOJhmezTa2M+sqQiBcGkTzKLgjJvXDFlqdBmye7zd3xI7HmSG2qtxZt2IpXR9vY6+jbOIRvhfdP5BrKdxIoaMxYp2OLYeO4nGPtrFnPkSfETOdW6E5Q4uT2NgnfPW1u/V6UgcZqdm6gsC5c4WSboHFCqUy2XgTsPA2y/g025eW8yiZJmxoBzG2sZuz6Hh4QplleQL+wO99dCknCnAWYv/tXMp4FV+svq0l0MPcMJUcZCKi+DPQL8J0sgCj2WbQKColNCevg2aSbAVdEHa93MRSNgoHRjIswXTZ0wlLSkzq0yzlek8AJcbiiX1p7m3NloJo+hRa4WNHOM4mTu83urDuMyg+J+xuU77MOm3LT/RYvLcm4/AQv13s36wwZ+FRVHcf4HOREC5430qZIqppzsuoR9XjLwn4RNsCjAe7KW7XLB21ijBfM6GJPbm2yxdO0V2e0kmn38y2Pnm6TnIg9WJeQUbVqRuOIYWXlbZ9VfMpO0XuvqF/sD02OSPY07Y4g1cJpMuU7mAYf5jqF63Hz4jU9Xsu8uis9QB7Ppij4I1sYHhqacyGXbl/Q9h9RDlyKdxpAqn3b/7ZR1DCYcuXpVO+A+J3wJ7c1yJ2f9nZSNSXTL7vL2RmIvDxdQd4nYzek/fqfS63sUbByZKMag8NPHmm203xoF7CzdVrBzBl8O0uVg8b+2ue2AhfPqtF6NYMa9csAXJDOdggsxeiIoPGgKCpyb1kUAxyR2lVAeoDvug3qG9YzxvF6oU1zQgbCRN7cb2Cjc0gEi/G9uScAToQzT5QncuPSqYIAvsuwSyawamOXd9rzl8Jof6RgoWPmDSU3yNZaCL8PUfL3KM0l8wkYss+B1VI/xDoVxLwdE7em+PzcQu1W94xY/VUAyoAcTpRwXyN9b9r97qYgCm50G3u2L4gJmbZTI7FHJ9Wpx5EA7vRPwFc/kZnz+N74IDnPpHwyRgZzVbfB35/8qKV1DCZeMlrDYbVuDkWWJ3HuDPjtgW/xCpg6+ak/SUDyXNGmcXFvmCnG7F8/xMMQwdPQQ1pxCMOlpzjdBYYmaeQhHDhFLcTxPYJNZCU3tFf292iRkL3BGJdm5oEqO2fpquVwTsRfqAS9+SgC4W4s2UZpChYy31Qu3KVMv7Q5kCLSLFG/qXHcTa3ZJGo/TZCsuJrrtEX0Q5Ra2VeyNg300FKiCj/aQaP6ReOqYmxZ1TCVLiXzJtKou1GufPgJYgEdFWKlXk4bHAkuiX6zGdSnfUZFiCPB3fVERMx13oUYeKKeouJ+s3/ZP7S7HHX7FN33EeGxyNN0OJ2My1CIwCn8+pXZ/DyWZ5JVi2K/k9xoeBFqHjP3N6YugEI//azp8DlGOCi7rSJGRCwIuC9hbEGjujAQ2KqzFDsYmT3j50n9dDpgOgxHNxE37KXehcAmTFDl+LtmK4Ck9sHwl+vz/72HK/XEFKyMhA9VFVVHihm4v12V3RhnE4rYzc5EBqlDEuS13MA4lIGxnNmLGe6b/6g0sTulbHnNsTDnhhiUARwHLBRlXT0aUtOMUkeCDfRZUV3EpI1n5EsCFTo1u968mEHsrhnK0kvlh0Fz7yqBMiEJREdTyJc0721tDmKSJqSXaL","layer_level":1},{"id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Capacity Monitoring Endpoints","description":"capacity-monitoring","prompt":"Create detailed API documentation for capacity monitoring endpoints that provide administrators with real-time system health and resource utilization data. Document the GET /api/dynamic-pterodactyl/admin/capacity endpoint that returns aggregate capacity metrics across all locations, including total available resources, utilization percentages, and capacity warnings. Include the GET /api/dynamic-pterodactyl/admin/availability/{locationId}/nodes endpoint that exposes node-level details only accessible to administrators, showing per-node RAM, CPU, and disk utilization with FQDNs and server counts. Provide comprehensive request/response examples demonstrating how administrators can monitor system health, identify capacity bottlenecks, and investigate resource exhaustion issues. Document authentication requirements using EnsureUserIsAdmin middleware, rate limiting at 30 requests per minute, and security considerations that distinguish between customer-facing aggregate data and admin-only node-level details.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminCapacityController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00","raw_data":"WikiEncrypted:gKP9HYHAokeBckJVfvEiH325zO2FUZgafxMdqDTenfiADMILiieIEmH0kNA7ZfTMYbKx7O0jd8q/kKTy3/q4QynOxUF5cPpGnvlIOd+vgslIh+nZVSKwsZW6YWyFMXoyPPpMbH9zDoSRZYNjakTZtm8uh9nVIPcd3g6Q5u5ccXyMMXiJfl8QrNPO73V3CVaap3T49B7eoRUYgxufbHfJoQxygQGhFaYnhwxUNO0sOzrsRo9AoOsG7R3QHGzE6qzJYr4a7L83DterwEBNFpr05GW712iIGdqeEvnZ9a2VNycfp0RdTpZ7gmxcjrXG1z6Njw+vqLvFIwzMU357qi+H+jcW3WVKpuT0GUzNNMcnoVqYNhumbAoJ3oU5n6mIpzShs6i1oroaD0u9aqhjMj0ndPtwNoWqwYD5clOoVB02vez1/hOTgAAHydkSSCQA++pYdbpp57z9xI687NsCv18uq1XJKdshhO9dSbghdbNmTB+5c9/ayWqHSx3NTVc0vIN+rdIKTavlLNHaidRF+46LRD9K4aUs4u0QJjcF3TJY1U0OmEYVKMRYz4C71c4awOQSnPkS7Wwio25SszrRUhfERKWnYb70RgR8e4DrZCLugl0wGwlq1j78QcbPYzlXraknUJxzY3Moph+rxR4MMj8zCYioc7DH7DYKuwxiJeMZEu3Qmg9Jojuoesndck1qdYApQTTNOUQjWPueXSZhG8XfI2frcZ46Td1B3/DT/p0q74G14mh0bRc5R+yYMK3djnAIc81p76HE3Ed1iuu+3U9yWoodllWY4YQiuqkGQrD6AiHjrNnLScrC7Lk6r40bhjNqaJSkK2i1M+LYKM5ugDshi28s7NnjO6B5jBRRQRFE8Ua1moVoNAOPajM/bpDstrj3+LtBuKEkBPF/n0mtNkyVJxOMw4x5nSQCS0iHW70OCiZpQCvc+jfyVNYq3AHmezm9VX8KS9+Fjs4SLz311sFvTBpZQ0QRBdCHssI5X7+VqboCBxC0cV2i4EOiu869rjbzEGvooJceXBwFrex74YRtOepI3i3g41ap0/Yg6nL4LBRq2MSvAn51mnInkOCELHhTI/ISJjI01fEA8E6XEJaFTHn31SMA0we8stu4cEBJHHBHUvZfw6O9uvzTIoMzvnFjymL6x0lV7VH6243v5t7krTTPPhiT5qcVoww8YWLD0TeYAFux1gZIJrWeVKrdCehew9HHPmRgyj631blk/5HQKPboCQvTEJAGo22e/Ri7D7r4Th/L7qsW3wgcOjqEP/6VQqgO+MTyRm3dBJodwTs7xhLjnP+j5hwMLCGmrJbSDclLE705n0+It5LqEeNGeGveq0BFvTGq2hVes4hWoc+gxXtTF08BdNQ7DR2kr9+ZU9pwV3vry7GcmHuxEJ+Bmu0/w/QdTJrFzbig1NSFdBM/zZ9aze2D1o4lF4mbGGop9auUC+TkH6obV57NV37MZDgeC+/5UtsTB55BJIz4nZfkSGyW8g/+d6OVA6awgYRV5S8ko7WQkiIPK+IVWvcvT0H90AqgUJjUTh770ft9psWKXm29SLaB69ozQiTExp4JxL4KYCwd37IbxqwOZwn1VhRLgdAjFq7xsWY5eeFNLLJBZZ9fWOLphVMnPa6W3IAds9vYc+ZKgVMYbDApfWupxhzXxvE2hJgmKIW7IrkMSIpmCeowrm0oGFj00dDXSdzTj4r0dD3n2tKk8qNqDCciHxuxoPTALva+MacMDPh6CWq7JfP8q/9IjYwC0mvBvO5+8oERgl6G87CHYx0RuB8gyGsperfRgfxhvj1avYavCvUadOF4avbtseJ/OIAAJnOZSLSVf3xweuRtNASXilvkx3ZgafMDwahbhKR42WKyhx/ARYKmqf06sVVJq+HLbTiHoNaU1G/Jb3fwHuGrTqO7gLoMpa3JS4tkibW5+9YzAUsB2ez8pQg+vpMbPIsYMN+qouY=","layer_level":2},{"id":"c34de209-e200-4523-a028-b7ee197969b3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Resource Calculation Service","description":"resource-calculation-service","prompt":"Create comprehensive documentation for the ResourceCalculationService that handles real-time Pterodactyl API integration and availability calculations. Explain how this service provides accurate resource availability by querying Pterodactyl directly without caching, ensuring customers always see current utilization. Document the key methods including getLocationAvailability(), buildClusterSnapshot(), and verifyAvailability(). Detail the architectural decision to avoid caching for accuracy, the batched API call optimization in buildClusterSnapshot(), and how pending reservations are factored into availability calculations. Include examples of error handling strategies, connection timeout management, and degraded mode operation when Pterodactyl is unavailable. Explain the difference between node-level and location-level availability calculations, and how the service aggregates data across multiple nodes.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:44:10.5583264+10:00","raw_data":"WikiEncrypted:WRaIw5LcDrebk4yzceYz76KRQhmpXIdv+Er/u7CVkqImUNQAm2bnSne33LdsLebyG8y9+8M14ycVfRc+fZpF1TU3tPFrEAZ6OGLYQeY5+fsWegqEUP+znWnqpIpHeLW6K8c8BqPUEZEw1ksVoP1OKeOw9EpQv3zdpsi3xdS4BRrwVLkTbs8vkAnz3SsruVDT03ebl59Dl/Zajgdn2g2iQM1hNEY4ms33t2RjZ9uhMoRkPIdno4D+yHanNJcFo1463y3GS6yYc2Ph2GHh11xbhkflkRfcNCBFYg9GgycZQmVcS2QQYoaf9ZkH9Wg6ALr6VCaGPJImIF4efd58SV2dMwCCoabQqIurGp1BRuIIo95eLt/PN8f8LZIT2Ti4vuGGcFaYAaFkRCFY0w+6eBBpUCtdoGRUcsXOtArNvqezwCA+J7YmfGJlp/HRT2Y1SuTa5bETZR0u5oAcVY8iuad+DrVJQI1WA622E3x77dP97Qa0qk8LqG2hhJQbw40pTavODtlL/FVplbLrWcxknwLoqWuyFFiJQNhpMf6W92D7GqxC8BPBO8EK2Ytfm2gcpVM3EFqdtn+6yUdVLAQJ6kh0y9cRQMk+rQzCwSendQ+4r5restMHeAK0VkpgR7tj6YwPL8F86t3yYv/cWMiZOQjoWnpb9rwJiZsiJ2JV8A2SjJa7E2m240beP2igMzSfXwr0dGJpIQ9lGXXP9Tw9ekd17QcVbhXi7/JxyZ0I8Gqe9PEchSyQySPL1UZ0OZSqduPbenQ2wMV9G5Yz5fgeJ+MmbA0x8jXnURpP8ls/kpIIKbqj8PIjgXEBcDCE36JaQ9R+MY9vz/vVYBXqjPb03zGG1z0M2d4DdJLznzp70LZBBtENSjLpgQTIZ3Ka7wprqa17t23VG4zGjOP3+CZBoGGiMFDgHLDiEHlXOjDRqbG/JiOwQ4Ba7zIKWuKDLkgsH+IK+okDV4kSBWpM0uTGNvmClGgT3URCW6bvmsLEle55cDeqbRDbs0QjjLjhcpnaQyGIUsLWV1FuGzNjpWSBDtRTKULAhYQpl2/S34ROQbvre0oq70HqguvB+eOrLUjRfQRKtLHFSofSOEMZ3lzD1GRzUpxXwWOTzv0ENpavdkyzVooE8SGy2Yn/jEbsoazNDE1tlX5kBLemjChkSSUAphEpW8YFqeu8HJUjXVPFFmppd8oTdxKGqMxmdgZHQAB1pMInMQX9cQ4ENludBWzcHcUGBTvN7Dstc6mDdsrKC+khnchzn2hAJJXMSA58Q83AwBkzsTE6XhDPwMjVyC9esEHxZGMdz/CRXOjzrg6jUy8NZT9cp+Bi9Tf4UXnMhMnXytvyaFxulrSn7X7YptfuONiDcmpJSe/GHQEFtNgypXobEEasEQu8BKd5yXtLfUFb87ZZqQqKrYnynUfFCCyezhVtaNdE5zE0icOgZqYFt7e0UZ8Y6DTCTfo0VnjomSuBqFj1IncpuKEf5O34AC4ENZPFbpHP2krc+mrRprNzriAVdSXEc4VFkCMZRdf3Xa9PqNIG553IQUPIHkIkuXL+HQecFxwLQ5oTtR2KjKeRWXCjexjR0ebfKcrQv3Csa75+PriCaI71oVY8kRJjcXXJ0lqDbBmoWDdGLBXLsLvcdOPXcKPybrmnnyhFMBsHtEYgWL/hQamMqER3Nc4b9U90kOuo9RJHY/hTrmhvG+Kqb/KvIztTsRp8bT6xkAm8qZ46wOtdMy1qN1AW4Z7Z/CbucF9uPoJQ1AEcL75cZa+vRiBYNVWnPubuxmN9Dmhxp9p85aklNYzOmQsLD/8R+tPihiBPRn6vBI0K5jFrdGoA1ojohzE=","layer_level":2},{"id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Cart Events and Listeners","description":"cart-events","prompt":"Create comprehensive documentation for cart-related event handling in the Dynamic Pterodactyl extension. Detail how CartItemCreated events trigger resource reservation creation with 15-minute TTL holds, including the complete flow from cart item addition to database locking and node selection. Document CartItemDeleted events that cancel pending reservations when items are removed from cart. Explain the asynchronous nature of these operations and how they maintain data consistency. Include code examples showing event registration, listener implementation patterns, and error handling strategies. Address race conditions prevention through pessimistic locking and transaction management.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00","raw_data":"WikiEncrypted:PAEsB8Ju3fT5vQaseGI42DlQoL6o6U5PuaNjZtoRczbR+sX088bPDHqLSdj+4gtb4vPAdwJCZ5oyAY2yU5QlRjmAgqBgJ3XHm8frE+zN90aSDTh/0Fl2hwi4R6o489zl2jI5QoDK/NxjAeoVK+47QF1TRPd4WWeauw9y3LBoKBo5+hcP+ADMmUp7ht3Tb8e+MH9DZl4aEnJBoO7nSu2JpbAat9xZfmTrErZQml2nrgtOMC5TSIeWG7aIEg0cBmDgW3UJ05KxMCa6iLr/QpVckAZKid9o9RVtD2RfJtYZ+30sqF86ZTriYQM3cON0viWaQlRM4JVGdIbe8DLJGjHM/TI+Pj7pxkUlSwvX97YcCtF8XqXgQ8Yfyt8gom2Xw5VAzA4LGnxH6oCDVDl5AwwZ1NKvgxQAPHXGiszWUYTWo1mx2YtbGpl40d6omVQWuQBtCf+LF16VKldA0sxEHcirpIIyhQnE/Qnl3BUHp080TN3YsrTiwxjz2bPjB9ibw2RPWY/Acyk2yDZCUqmgnM44ANUKrxzXnK6cGdLeDAFoUxWpYuc3WhnO29y5fMhc9O36qVc0AtLg8emw29/CAX9dV+au8IlEuuC0nGgOb3dYN+paZueNzUWpqfw+BEkBjlUmCb2C/snq3JhAxHip87Nhdmggni5+jx7Ea0cc+r6WoPRRLE5c5i+fb3gJ0CSrP69zVgOZWthDZgG6lGE9tRHXWuKXU35ZcbRcse3G1pq9+0xtHAUfehxaQRqlDIJkpqjkqSHRKVyJV3BS07ZZmJMXcMB2KzuXLmcEbaEAHSeklphKb7WJiiZ5IgSEAQKxG36XDSdue0Bz+V7i8IutGmuC6ON2IT5F2HKXQGi4N9oi36D3yAKjAkuvMLTjM286zg2iW94gjmhgsmV/93JKGQv2W6SxU11sbyPmJBszzRDKJyGXB7eRt2qJ51p+WPQtznsf0Jiq+bE75+Poogb/V17zLxtCPFOEG/HzMJoLEXEfsqWP8sjKihYKdAeWhvmeZqjn32EyeW0ZSul9weiOUDXutPrN1IwCUqlLOPhR13sAnfDkk/yGiWdGtsAwqJredHvUpgtNqzxTbrUzvyhKGEWAF/aeypitgPomGB1Cv8513se6ZFTCot+VA0yK+4yJKgHrlDsjXE2/uE8ickP6OocVxDKkpWaUGR2MgY3TIh+eFqmLv7X1xTdV3MPXezmTzsdPbF1vJSaj+FGf9RLeOwKJtA==","layer_level":2},{"id":"cae4c946-defa-419b-88db-55655e77ad15","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Architecture Overview","description":"architecture-overview","prompt":"Create architectural documentation for the Dynamic Pterodactyl extension. Describe the companion extension pattern used to integrate with Paymenter's existing Pterodactyl integration rather than replacing it. Explain the event-driven architecture that hooks into Paymenter's cart, invoice, and service lifecycle events. Document the service-oriented design with clear separation between API layer, business logic services, and data models. Include system context diagrams showing interactions between Paymenter core, Pterodactyl panel API, and the extension components. Address key architectural decisions like real-time API calls without caching, pessimistic database locking for reservations, and the strict reservation lifecycle states.","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,02-SERVICES.md,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.6236221+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00","raw_data":"WikiEncrypted:EPw1VhZSv2AMLpYzHbCG5biFcgGMvwOBOVUOBtRMzXq9nIrsyT+EBefN3hNUPITPVarYYS5Pu/iqKKh086FV2DmKzq7AELY1ngI7PIP4ODjdYOb+wSA8A8KPn6IFiIZ39WNHfVEScci3wq7im0bAgqadyrnE1Nyhq2+tV2hNX9g2li+IK5SHw6058IxhfX6MtSCh5TlDVxDQ+nqNNOUIpa1GLT+yizbwvr1zaVdQeih2RpmxnWVPj2iVzGEnuaqrKEioVn4cD8esSDoZnakSs40hiFHsvJ4yW0ovotM/Z/RLb3icD56Xtn/egnrxVwMe+a7GE762O15x+xqhIlYNCBNrbeZ4DkZYWTAnbICguaughPo6mNNv4r2pFYwADO/lsRh9l1Nlp05xjxo6Ku5iPV2zpIh8xSm0AH1+lh8JQJNw56h0oJr/DuQdSToOKmpVWdDyzp5zqHbzoCP+6zL17zGKr2jThSmvqBhXfG7o63ZWzqqOS+vedoEcMC91o4yL99cIZD61AuGNir88TxVORv/U+QqUq8ElyHlWoGGBGBJhbLWx9ToF8sWt6RgeoAIeCYS2gg4egDm061kiGZjGzENP7WTizOXYwN0QPAJY+l8RB1L+HF/NeSfH1AdpEUvxAxdHgayPwJ4pEeBmodJO7/Z63HhKl7gEzTEH+fFaqgqSx6lGeGYeJucdakx4T2sgxYaow/13TQvB0meSB+7I4mihc2384X0EF5QJaEWYHeS/dSNwKqt6B+CR7TfxbrkueJ/HJf7cncqpEqVhb2dpURrwuLZv079D9pxTWYr/cSwEW+GocZdpc9pa/CfQopAcWh7R3L2DR0iJVF9lMbNmnqPf5mUVx5QYj+Uf/01WFw2OzyE/96cA/9tBijKm2oJO2iYPWL8C6mP7wKPkiKAV3pdY5WqdJwE2b8DjhsyaDvulZPbIIMhBrKc1WYK6IkLkIBeKp2jAI9WZ/9aRkWdt6jjczaWZYeIsqGWbhyjiPNVwNW5WgM0G5/BQcxyknMJECBkl/GziEj8xbWGl25VFGSuhapq5gzFf4nKPbuZc6GcorZijrbvKHMv9LR9Zw/rXuspZfFVPpeyWm0A5N8Y971yfkntUwxKVYQWA1+XY2ghh2DAN8Ym3n1xBRdZOHeXsaIx2o6hwnT8KGwgiduxFlWfs6gIJErso0+9/5f+lK7cjxZOnJaOuiXSVZj1pJGcZcdEm0BcRPk1tQQ241JFcgiBZpy+BmkZVgOxYiEtsfRa7ixA9ceGFBgxyx6CcwPPy5c9l2nMctoNAnhw6f6hOXOzWPMoM7UjLJNIn42Ur65a5W7k4bxQvz1DW151DlDu6G9zM3Z0xC7xWzk97dQdeUJZb8kipSMKrvEvMhgvV+4dFcMkf15dRtLBacnjlR5Xb18crMz2AC4H2oAvNSVCFg2iTxpBj2fuJ3NQKNZGpyDpZzTIeOnfVyblHvMAxoanTOJhEXSU0ied7c54xEVmM5IOvqYZUuF0d5zTcrDXSHbS6jEoEFIdhXhi33FUjQw0oA/NzeyvyMW0acf01JqPHFg=="},{"id":"f36492de-4fea-4b83-8237-0f42aaca10bd","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin API Endpoints","description":"admin-api","prompt":"Create comprehensive API documentation for administrative endpoints that provide system monitoring and management capabilities. Document capacity monitoring endpoints that expose node-level utilization metrics, reservation management endpoints for administrative intervention, and availability inspection endpoints for troubleshooting. Include detailed HTTP methods, URL patterns, request/response schemas, authentication requirements using EnsureUserIsAdmin middleware with role-based access control, and rate limiting (30 req/min). Provide concrete request/response examples showing how administrators can monitor system health, view real-time node utilization, manage stuck or expired reservations, and investigate capacity issues. Document security considerations including strict admin-only access controls and the distinction between customer-facing aggregate data and admin-only node-level details.","parent_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","order":1,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php","gmt_create":"2026-08-14T18:30:02.4382459+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFPnQCmwwfFO5MgWRJLXlupOxtwLWoXcGT96eqgtu2S2Hsb8vb/Th0I0EChsokzmOVp6oL2EoSZFUWUQLVOhWbam5VmrSvVg23XiZ2IgwHbOG309k585Vx06gWCzlYYlrTpQPfNgmBenzMYqDubVMhd1FSPC45+QL8MHJvpJhhZKpMFAOlAJYzJOdtBii6eIO/ODrbYQCRdrQvOLszkfFN4+E08r0VNTj3bv3BG/rax3NBSnDjtm6CvmfViWcS3TV1cUE3KiMmTDnTm3cssmoqVEc6nlT1n2Q2hYsXgV8PR+pErV1xoaYQEcwjvmsqPRSBUgiGIfSHYJC0SGnzxnsqximBX3ozqwGK4kRppWk3ICwRor65CrKUI5usjDypVusScbBudNraLxazi/+dGJslDB582OBuni6acESJQJjEtpEMJmwuHdyfCBCLtkRXFXPGCUFxU8AwMsp5Qq2Ra6is3yVetQ3WCyv/8pyQW1knoHDuxfJAUk5HP8hdOm4cmhmATQSNlY7kZLGc+saFOhek/eFuU4/Nih/n3GCe7fmZNOpbslfGCp3QZ2ezaSfdMYbfIx8PT/M0FsrHK4rG6xLwvhO6YhhynbuNERSw2o7qILsItW8Cy1TTQFNUiM20J7aBJgB7xwpevibqxvN1cEfj4GmNTd3/bn41ds3Ue6vpqtGun8yD8yAZC24WSSb8VHdqAY79A7DmyRpD3fbrT582o0WomqEbLJBKcNJ/yKZDMl0WvT3o74MTkdki5oM4cAtcBVg2uSIPD2BGxdBTE0MDWnKU7rfLUCj+MgHGvLl0LIrAhXZbGanxnGIGbATKr3AtSawYMDe9M5gZUzNZmXVSu/8x2fOrCkz/Dvjc8MxK/QkY6RNg/vPcu3wGlv1eFfsDL9sJuIN2MAGIYJZPKQfZ+ZYZo8YRHMjmTj/gK9NdNHfNRhdo6PWWPc8KQtHGehBx6kATmNDL0dw7XHa0Fan2wcegR48GBYtXPE9HhIXeKMwESrb7u70SVOhzq0wQBJoQcG48jn8Y11oMWlatgKXyr6+FoQO0oK7Njv113ZczREC/VCPfE2E3svx5aiRlYStedcgornPBUvyuywqAVVdfe3nd6UJnzv9NUMsNuMYWI2l/lFWqymguJR9mfoiIoQbv8PsEvq3S37STEp8osd9eisOtHMjUbN66RLJYoMYGOz6nFqJD49gez0Q8uZGAOhFJzwjtt1gQ+8J44cZ909hvpbX2H7FVolED8mvBRQiN3wHcQwp0HiyDAxHz5LWKIMGWfS4uSYucy6HigjyJAIupo/IZG/KkTjirZWdM3KUWcrNOUluzz1tmXkG4eWC8ht5JUlk8cf60Ax7ee1f5tcjJkwHtC/HtVE2c5OVec/yW16HH43uz2fWqRC4euJ/6cD2tT+LhfUQoTRLXU/K8wWmnuocc6ZNTYmPEW+BwXZdqoYrJgAZufHfDPTApxinaNrocAegG0rNr7B7ACUJxTTWI9nmucQ+7eqK+d3ipfW/DYDCrhdwYiZ5EPpEWAR/8NEv58U7Zk4b0bW+Af1FfBWTPzqQu6BtRfPvY4NrQxz7DTRhVhJsX+m+0HZQjkYJbWMovkQdP1e2J4hi3wfrrgmlo/eqRXnbJzBj5ardyAmlWBuHJGlCpMyHU/p2CpW+qgXkVKDmIk0bFA1AXM3rhO+N8QtxM++9leGBJsk5KBFnOQg/n+6HXjuCozOcHsH+bsfcJk2fQxxSRnJKzieIU2NfCJ1fVAS98/62ZGYtXMbYuKSO","layer_level":1},{"id":"2babb181-df9a-4da5-b222-f75f0ec91241","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event-Driven Architecture","description":"event-driven-architecture","prompt":"Develop detailed content for the event-driven architecture that powers the checkout flow integration. Document how the extension listens to Paymenter's core events (CartItemCreated, CartItemDeleted, InvoicePaid, ServiceCreated) and responds appropriately to manage resource reservations. Explain the event listener pattern implementation, including how CartItemCreated triggers reservation creation, InvoicePaid confirms reservations, and ServiceCreated creates audit trail entries. Detail the asynchronous nature of these operations and how they maintain consistency across the payment and provisioning workflow. Include sequence diagrams showing the complete checkout flow from cart addition to service creation.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":1,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:08.2203921+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+n30XbiFQ0QQI5a6lxogiBPjTg0DvvbBFVxLISoEha9gTHejRqEmQELBgKy8TpInzeOxqTibbENEoZBYJB80m7a8AkCUYjT+8XutVQnlBsxW6B7AxVZJPt8dBsk4/NRs+3Fs9Hy3f5vUM+rkVyeRDU/t4cBM22W6LsubJK+SlH/camNzUFL9YraDqm+kvr1KK+tqrH7Zsqbfc0YpCXQQZMhmQbRku0lZPANjG7wx6ICPWbd7qTQHkXeTJpfEkyJTvKmSoIMHghCq4Po+S7kjqYkDr4Jri4C8tCkMXodvNquesgq41stmNXIugjD2mJeumh8gEhunKj6Xp65wbiwD+6pHdHDR+fEbB1N8i10vzzuXGy+TNfPkfhoAxh1COQu8H7YQuZz27PksUOTyeonQyHZDZ+HrTFEn/PAKCy7fXZxcUqsLRmyBcw4Ycm8zwWZV73BXNrGQyFBoAZ2N+IKPqr1H+kFXJqY6V56FmZ/4C3dIxEPyJTHCZQ1PDJ57wcILfSyX4yQ3BW4H6BXV0eoIzraLG49iAlOlc89oDBSZf26jGZ0zakzam3DbnFtw1a/s0+NhFLYTZnubCgrhbaPhkcs9pwbmw+oN2PfWkm9O6M4gqDJgnV5Y/61/m/KjhnMer4eoJYRI+TJBdJgrLHvdgkOjLHteMznWwt5uLVap3WmjOtb3AWqLMq9QJMqcP3trj7ZZSTvwgDHOOBMP5Li+xtuRTJgM6gF6TkkkZ+jjDkTOZ2OtctGO6qPcDC3fopQ3pj3yYsn/DSljnX5rAlNiyfZ7Bg8jwJKwG7lTvDi+FEBCb8UNh2P8Q65ImiFamKq+FgM4PDt1N+kFfDFDkRQPpcfU1BIktJ9wsqfOeqly27FE3+Y4XqHWSPh4EIENu4n4aR+76vbpoxebk7bEpUQiOWr9EZhsQFbAgqJegBVnNZod933FxlH6HpoNLIm+1XfidbgKgAZGzh9H3sOP2Uo8IMy5DVKXDNKNDqTBnIkIizNAw7EkwChP/HB8eGykKTGHH/Bwdi+5GJyA5zfiGcXkJH9s+2ATPGi+BOZSatoXUBiXLzQvNX7NOvE05LY/oVFuPkLmi28EvIVwom8FAuuYabIjxmGWMu2blrYgMCX30+IJqtz1HjBjjDbQGGzmJ0KKPrro4pgQZRm/R/DG3ZFpzklu3upBd0Dy/qBtB1XILg4yDRc71Caj0bVTHS/vck0zGmkVNKSk4Q/ValrtDITP8I/klcSRfnGsi0nN/0vYpeRtsis5Gw5BwnyEgpZ7hoXGLx3T0ipD/kP7/ATMvzN0/C7nvqoTM+PNOUWqTDpu7HbsBlLHuEFWdVRvLaKAybKx8cOIgVwCi3tqSvM29mePu0IZCHp0a9237e43RrTwJfDo8T8UyHtBZCTtqRha6Ro+hn9k5kXTH+FEHfq15W5KLy3SvXvWAG/G8yq38/d79UbJBjcM7Vwvu7ejTnbU2xCm/JZHZCO1Lh/y2++5bXwFM4SLmSvCEFA5iF62jZUASkE9B8/1m91bptGEnP2GKSg8IQ==","layer_level":1},{"id":"f090ff65-6cf6-4648-8dce-03419ae86c77","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"NodeSelectionService","description":"node-selection-service","prompt":"Develop detailed documentation for the NodeSelectionService that implements intelligent best-fit algorithms for optimal resource allocation across nodes. Document the weighted scoring system with memory headroom prioritization (50%), disk headroom consideration (35%), and CPU headroom factor (15%). Explain the selection criteria, scoring calculations, and how it evaluates multiple nodes to find the best fit for resource requirements. Include method signatures, parameters, return values, and examples of node selection scenarios. Detail the integration with ResourceCalculationService for availability data and how it handles edge cases like insufficient resources or maintenance mode nodes.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":1,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:10.9300315+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPU1NZT5lCZZWgY4kA1m6Nsey88uVCxSZnlNfYBLgPfLOOSgKtnCVZ2xSdM/4qrNwQM97zggPAHw3L3MzBmJJMKdbAvGXj7asimVq8lQYsM42bpHg45aSiwKMuI9sVSelRUDuXUx9OAOhUy+6RA0PI4cgc9FGqgGzHEHdVEN+tebL7R/yQpFiNOf9pJayxwo+WbpBlI3xtc4WxL6MyKdH6ySHouuAFJ+3KaVvCXKlQcPRz8Yc+aQyTAUTd7KWf/UNW10tRC1DfWJAc5hJvapgyRQ8pKYZNeIejsAi22f1c7FyBKlQxMKF/9KHRB9TYIJOhB1ILCzLGKBbzvhryyLIXWUnVU6naODxNsVBnPLWjNhP2jrGWAS5WelkLkWgUqvRokcFn82edTzpJPU6miV66Y7tWSqFfJg81BRmZnFoBCB/E/jpF0u1vhCRDP8XyphtRmPZTXZQGoFCtDPAtUzwPBEY2M2xTvFwp5iOSCOGTCaDiXXg5zvbeay2mG1+i4UhilKZ6aVN8lxt/pcmFI6sd+IWzOAUGsQGuFoC9wonxOvsKH9d1eFQiBeZPbSBuRSeoEaepVtVdFGKmx/xJUWf9m84Mm6aMiFds+ZSXYVwMqfA8I4Wv5xbpFZXLV1o+9q+gevqkcgv/RluK+OvAliL5G0S5cvRGql3QhlK8f/0clLf754EHfWbikMlXuTvKxoS33jH31TllYa5TL9BhMpV2JOTBO2pKIRob/YFNAXUrX5DT6RZ8cYc6gDipHTFBXxmQXk59sNsPNz/V8GPbNGsIHRMtzIe5FyPTWzI9GC6vus3SynAKBLldk6P7Km2BAsZHOsDt2qyXTqPhnio5lfomXzDaZAr+9y7/2nvhbfXx3sQOyrfRgzJVDqalma+y2zW9rgSMMUNW5aP5aApdDyeB7TomIGCHU9x4HI1YqBkfAcW+UEdKltgI1SyvdFy4iCaVleAu8jfUeYABJTypFi1MA3+IbGpSTCOSUYfewl2dBstg+ZolNhScj6DN8T/R0HYYRvvHRq49qbs0u6ZNLsLFo+vAjTtJ7FggngE6G8cMRh/2vPTXtth5vhciF/BUowwhvi5Kzt3fJvWZzBFbyjNqTtsOMYxqpoBDuml+z+pZq/LiM3nPGjYLr1TifGQGZcLVQHihAbn+EukkfDuMp66dzQW656HSGc3DttSPr34K3YkzlQ8GdkCGnmDASe9TfsmdXfQ2Uvf/YQTsIyt/hTWG6Q0CtluLS6fxfITfckBaPQPgBM+8JX2PbCp6c2XZsno3nxhY4j2ok0IIscAps9Q3gLqVfC3EdVg1GAvVApUNH3uxDBYugoBAlzJKic7I46pof4d7RLPNR/q3eWbv18ZA5YDXHtwnkzwL6VsrQ87S+6jA==","layer_level":1},{"id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Pricing Endpoints","description":"pricing-endpoints","prompt":"Create comprehensive API documentation for pricing calculation endpoints that delegate to Paymenter core's dynamic pricing engine. Document POST /api/dynamic-pterodactyl/pricing/calculate endpoint for calculating prices based on slider selections, including request body schema with product_id, location_id, and slider values. Document GET /api/dynamic-pterodactyl/pricing/config/{productId} endpoint for retrieving slider configuration metadata. Include detailed authentication requirements (web session with auth middleware) and rate limiting (30 req/min). Provide concrete request/response examples showing how the frontend integrates with these endpoints during checkout flow. Explain that this extension NEVER calculates prices directly but reads slider config metadata and delegates actual price calculation to Paymenter core via Plan::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Document error handling for invalid products, missing configurations, and pricing engine failures.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/PricingController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6978147+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00","raw_data":"WikiEncrypted:KrL2QibOSZbLMlUoFPtX5FYrcUjZasYTwn/UujzkoeKbF3ty12OCKFPTLg71evrJP4g+Cl5S4PwtQFYPhAAcH3yvug3JFZmsM9Mqvw55rdI9Btx3wiNcthVQW9UHmAI0p/KYd6i7hKUbkv6Y8jZWtQ3xy2St2l8EKjlkukXBvdV417Y4HjylORnnS5eb3w8SSvJEIc/AVfpe7pCDzbk/VQimd1ouaid0LwSz1V6lJZEqs/yNa00ENj2MxRQ4C7/r6fLW+GDIM1dI8TiT19d7Oeh6T96KEKPRpsYgU4YV2asQ3FvmcPYvVWujTwP1uVKnhJ80RuA8/j1jFhQonAN4Ob/Rz6P7opeXZ3ixK8XTcm1x0EeG71eN4gzglOmRR7N3O0nxsY3irjWdKTSp7cw7y+tmKuQNYqVqLN7pPWd7z1xLdfNyHQGiV7ksvVKsEJiAb8xozRSzv6beOHslwCUIRH5ypVcvYoNnsHPCq8bufG4GRtvidqSD2Wsd3fZ08EaE2ljCCmIxHHcfIa3y6J7paIqWzCF8Q/2KMryo/MfuVOcMht2Tt+chKyeVANBpM0LkSilFqMjarMTF8Ya8VwTiNsQSFMHg2pA5G0HiEnBrvnbbImaTVws6Mkj1aCMbhmU2mrPwUPhl2tL0V8jxUrXI/n/FgHJpik6bRbYwDcgT9QgfB0qPensetG52vEe3oTVgOS0uegterkU0qTiYLy5YZAc7IoMGNaRVgkrPrWgyTZCjpYbp8n7WQckDZwxBs74dSs1sYnuHlCi6/cRdIYQjF3dYktz5orFA1RMq5cgNIHAOQpPyeVPdxeIN6TSd3z9oQY+TqUy2ezpaBNL+GKrB+TXpnYEXUA0M7hKVq1OGvdzFDL8y4BYz3zRf90bR3StF1yBkLqI5aiSCK5WYg8nyZJ/Yz6okaisHVS6TcoSNFuYGp6yaVvBwQL31VXf6Hh8klL4g3FyUv0Zx999CJed/S6eY1huTX7aI+sE80v6uC4M5xi80LkeIWpQtvcrm1YAM9LQF72IgNrACdU1xBvNqiYvvj/X/c2F9zNl/CxYnIdc6lJyhb9GRy4tKMa/IBiCxGcAt8D0lJChiYTG+SRQbiYbnvmsdUZPzwIy0r9smQgqpZiLwwCErhZiqNcfH4IrWlwR/oWKYQ35OI7Qu1YNEvmJxxBsZiIeYwaw6j3AmQHRvFu6IS7FwbNDmD8+cBNIeidhNdvzpCgegzixLIS71wEX2lnzoUT2xsIcudWJeglgYnEjTeXiVT2z0FjcyVKL5pCBmOQPulkuXpLmrkO0bgZES0wRqnjvPz1EFogPMoMB18PzvGeRWVLssAmhMrPWt/LTs7QXgKqcCbjbsGRuOl0w1SlEQ6M7fQ71p9Ln7ujjQmW1rFVO8g9HBJCEY6tZirXMbrtidcAZ5/WbUU1sNzGhNvFcjcnuWAKQ1zaYeua6PosDjK98Yo2QxXfsxf6IlRyvw1hShQhvJP62PWDdaMiDnGOwbC4p/8aSj4O9f/5nJosdJI7ny9+zLZCDwCozhOCdg58d9lv/uYQfj9ZtEV+9La3XCFeuISi+AMQr5lT5etTR3lHCHS6jSVIdnVuPEx/MgqVbwf9l9skEOODASkTCR4g+b49Qrvpujd2LgAGe30wTtef2rrAVddZvtb4b8RuA9tV0rJJKOWpNuEhSvMR6diY+EvFCUKzuUkDKGZqkyEHURjRwBw8ydDExn8YZUc5K75xfuF3CLwijCQzmrZpjaAxTnpmk44tvWMRolbSRs5WwcrmroPu4rFClwZnfXRwylEMvH7F8yknGf0fDjr0a+hvrb6zb4Wc9nCZ/60vYWjCZwxsSDPV4adGexm6W4IoseqMDqwOk4UNdpik4hU1LSyN7daCj6jcgRooG1Lp96ZaX/8lu1njskuOxvewY/","layer_level":2},{"id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Audit Logs Table","description":"audit-logs","prompt":"Create detailed data model documentation for the audit logs table. Document the schema structure for capturing administrative actions and system events, including fields for action types, actor identification, target resources, and event metadata. Explain the logging patterns used throughout the system, data retention policies, and query optimization strategies for audit trail analysis. Include examples of typical audit entries, filtering capabilities, and integration points with administrative operations. Document the relationship between audit logs and other system components, particularly how they track changes to reservations, configurations, and administrative actions.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":1,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00","raw_data":"WikiEncrypted:eBSK77QvZcmbCugIIal0dJV7nRn7NU6S/LHQTT07FMuoD4PD4Cz3saFVCxkw5e63ZVedJ83Ytx7iC/kNlGLurtBZcmxZrva0nqO55D3/Uup8nqSxblkJtZS8HqujneppGi34JxedVjnB3MCDR3iwlLVLMw1ICjMMlwm7Rr5SHxPc2DEyDqVYpEMZNx+HITvlM7NkckwmA4UoTVUDIqckToGtVXeqjuf8KmjZ6cqxRm2wLlf3hm5nWDtj1h0Ivq2kV2KSoMznvH7XfYHZPQuN5M4n0RXXaLauxxKpbOB7DmVJ+7pHj/VEC3IPRrnJggqp35jZ0ixUdWx8+Wn8J0IKOeUNv2xemgg2JEv/vt0U50I+8ejFVaxxYP8y4k+duaeLWtmBgyR2eWVmkzbMKapQ+L9JC9H49jSAehj+lYrG48KsNVde9gtf4qutxb1DvhXB95OnAMLwmocXXWDYEoOgVL/r9cSZfit0XdItYNdsVwskAs/GhV8IFvP9a+oBzJjdwqYD3vqQK5KAct1Tvynw+SOpyNEiYeJvJDdaPL/zpunnrK1qUv60B5dUDuKP1RQFGZlZ83HooLhIXnIRBJd5N4Gcmj6LEa5u7XlECV1qAl6UDn7d/BxXVur1rGHZrSqiZTOPhljgd2pyYeH6AgKQD80tzbtPHXb5rWWIHT/uV50WOhEPJ0KQ0jIpfW6RRS4UBRcIJArcZkV6du2YvyY+Vfb6eBtg9IRZemAw17JdoS99W3Zhry0HEywTShANtrgwibGC67i9TbAaRPgzFAV5T0NC3EL8woLw0jxMnNDwEw1IzjhNLAcwoyvs8KM1ZW/sMA53AtUTORNaNNvrsUY6px3L4IPjzzyCNvNRcCoMZ3Wfv0tVuRgvyhbXPExlHe5p31hNKLc7sHYNFUR/lGbXm8As45LkXeDPe63k3pZKU56FpEEPsRd7b+HnXwisH7M5cWBfaO0LjH2hsqP/aSL8+mgF2ocl5t2qXYyrLq8u5+DseSzBWceuVOBb0JY1JYkddvdro/KtAEwnb7JXK4+G5yyudSnPlHEEAywbPrg68lcplXmKOZBOq+j8TU9cRXFV/eS87pW7venRaJleiRK5O667VzUmRKLoxzYRh1x+Zm7TAAIrokDU+RjGuQ+5rIWOx8QRvCHZr/TSaRf85Mu9fEAf7zALHYJc0rPgbJHR4TQiwADZ4yA1OjMhYc3Aw7mQYzBBC3T8GKRLjkWRiywbLSHh+wNWjA7vjVoe2jk/DSP3azbV7g7jPfMmqGhvO4eWZpRdAmGo2fZs0/KE8Uj4z117ivunh/nKdThyc/0wAEseRCMpW+sOTbGWiV0bdU7GIp7w4ONVCOU+L0PstPAd5Or6NOYJmU9pj/pkvgjxmuTtnBOq2wMkkOh/jV7vHfqO3xffiutVwi4cDtfYVRmsVciT1dhaRCoi+9xLxpBVCca80mmYZUoLH6bXfw2eAkFe1OqOtIoZZVAeIFdk5i+axw==","layer_level":1},{"id":"7e59ce25-92a2-4b6e-b318-305975e4774c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Management Endpoints","description":"reservation-management","prompt":"Create comprehensive API documentation for administrative reservation management endpoints that allow administrators to monitor and intervene in the reservation lifecycle. Document the GET /api/dynamic-pterodactyl/admin/reservations endpoint that returns all active reservations with filtering capabilities by status (pending, confirmed, expired, cancelled), location, and time range. Include the POST /api/dynamic-pterodactyl/admin/reservations/{token}/cancel endpoint that enables administrators to manually cancel stuck or problematic reservations. Provide detailed request/response schemas showing reservation data structures including token identifiers, resource allocations, timestamps, and status transitions. Include concrete examples of common administrative workflows such as investigating failed checkouts, cleaning up orphaned reservations, and handling edge cases during system maintenance. Document authentication requirements, error handling patterns, and the distinction between customer-facing reservation operations and administrative intervention capabilities.","parent_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","order":1,"progress_status":"completed","dependent_files":"Http/Controllers/Api/Admin/AdminReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:22.1845953+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Service","description":"reservation-service","prompt":"Develop detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with 15-minute TTL-based holds. Explain the strict reservation state machine (pending → confirmed | expired | cancelled) and why the 'released' state was deliberately removed. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent checkout flows. Detail the idempotency support through unique tokens, automatic cleanup of expired reservations, and transaction boundaries that ensure data consistency. Include examples of reservation creation flow from cart item events, confirmation during payment processing, and cancellation scenarios. Explain how the service coordinates with NodeSelectionService for optimal node assignment and integrates with Paymenter's event system for checkout lifecycle hooks.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":1,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSla8lhwQGTs0yV0pj8IDu1UiZ6AH8yKUGDtfPXlQTy/fXRUtoszgFPGwJWtq0fOq/KnDMFtJp+AocieHLMogtlZpa0GEaCuQLGo7GsNQ+eKDmHbXeqw0p91WC6Tcq8rH8Obrn0P1/uMc1BYLvn3XY8PPyzsOaoDvgJdTRJNMyFNXecJQjKfv6rLXyEIFXLy8c7Zd2MMsPTJ4JEeW0QzWQCujA32fon5xBLoe8uRvybKxhF6tn3jZANqVIkOV2MUlHRk76anYF7Xc3KNXrr/UB5YzklVhQTlJkeuyV95Xey80p6VwTaL9VrC3GxZ7QQ6QCoZsV+IL5s3MqkPndGTkL3VITeS8K3QBIBjC+rdEyk+b3Mov9A+5Syo9AxXcUnwHTAmaq6At3SZGCB6ZBDRDCzRc/s3eQrE3Bb9UEAwqYt1J8YTQAg2mjRxhdGmV01L3k206nFfOZbZMdP7wbXJOzh4i7S0IyqZ/FSAENxNU3VbOtyQMwr2LWE1hQoVoLYqLzDK2aqRp171PDv+f2DF5xVRALSJA7OX6z1kc+TIqxLlTYKvSjZkbwVQzB5f+CmmPzvPNnJNi3XbOp/zBExCgq2zHuX7AcnrUb6NHHHL2vdJBnhhIaz2CaZkQGGgDotqaLJPSpz9JS4gKRqeO3xLMdXjWt2PdMx9fcyLjjqSP/1wTYBxzCWIlyp21I/7X9bGO9VLPkYDvzgfuf6f08/8iU+et9xFQuthx2bTaY4qztvreCPib68MfU5DnATaRS8++Bh4iFJrLKy6jpOEdn+HJsoPXOtcgYLPm3Ib+8uzhvBqTEFcncDiLagHCgC8pzlpeZJO6be9V/m6VZRih4OCYzdVmHtAJV0uTNMt+oKavYBm9KlK6uVjq2DpUDS/ZIG5+o4pftmhDa0RDcPvQlSXgjjlN5T/pmFw5laLtTZZbRYhhZki0tX+vHISWSZuNeodTjpI6qQ97WY9KZcGgKHsWf0uZ/Y2x73OOJbMuLn5MJxyMUWIOLMDn08EsSkJsLVi3BdK909/R+ehWJKdt3pU2rTvDnqQeeTExZ7XM37xNj1Wovu4VQeaJ3y4FUJibR9pVNKjnsEFlpL87FrvDYsHk+RzBN8uWm23NNbC5HiolS2owxyCWiQPmshIkJVAmmwF9WXX5UR2MmC8asB7KNuNLiYoZqC3HMGMHBZTtyVCbzQ7diHAuCGhrFKnTxNl7XCtgkl/NDWC0M5WVuiP0g4tmNkTTYVNV+HVlfDQjBOeqvVZQC+dXY4fnWwYq25cXEBHJTt/zcTRfJnhnQPdUKIyHOiaEhQ2VzZSs09nw+kEDbOFNxOEzpPftTwAn/DqnWJgjZ0ptB4dZvtkzXKnJN5E1lXX+RP7glCW27A4oqAeoCcF58I5gV1UY5E3nbu+N0NsHKETeYZ3uhvCj5AU5tACKN09T6W7P+oczLZe9rWCPl+NgEPag2tFCKYKXjBpDUjSidiqrDfyr/DABMavaAvmrMtH3rd7ChtzjoXgu5Rn4BfA+xEhJj6XGMk+uTpSvsR7oW+BI/kfM08lODDJp5+nYRb5IOB93kpaIcKKl3eoYuENELAoFCgxoavbuymntlwUWQWRyDgYgJavWjD73k1tyZ6RZMt2Z5R+uUjh24BvllnwDwAbrMqzXyaoKz9TfVQ54BUTJ7EJTmoB8wk6/Huo7m0PvabHkeA/1kXIsrNqe8lCdxFZ6CdHnpUd2McWF0PHkQD","layer_level":2},{"id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Payment and Service Events","description":"payment-events","prompt":"Develop detailed documentation for payment and service lifecycle event handling. Document how InvoicePaid events confirm resource reservations, transitioning them from pending to confirmed status with final availability verification. Explain ServiceCreated events that create audit trail entries linking reservations to provisioned services. Detail the confirmation process including real-time capacity checks, reservation state transitions, and failure handling. Include sequence diagrams showing the complete payment-to-provisioning workflow. Address idempotency considerations and retry mechanisms for failed operations.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":1,"progress_status":"completed","dependent_files":"Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,DynamicPterodactyl.php","gmt_create":"2026-08-14T18:30:40.3525775+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00","raw_data":"WikiEncrypted:lcOTJMVsDrhWtJI8Bt/2JsRjYxaJz5fmP97lIndtkE6QfsGRkOWzsvIHzfPSyV/30w5sPj/CB9wLl7SC/3nNXyqvZfigEZumNX1acZ0ucs0se5G/gVrLUvLPhJiIx0LL15hl55uDHC1qiw13bFSvEfsP0yk52WRlikTLac+g+ZElFtpHqUp8KoS4BW+PRI3OnRhBh4S4FI1aIijXWBljYkPsN5fU415AOP8PPG30/dM5ZFnUJ7nnWspuvpEulXhkgkpykkIIimoPP2NbL7q2v7vwxE3omklumTZ0Qt5ztn7zXjuy9txTZDtYBmLrmigqJkbnQXQRK6b/LemCdscnRqaHiB/6t60hsTcxbN39FNtqQULmzPBeAlMQOUp6LJJ/iNTuehZKoysjcXL5eqgLfTBnQwF+06cum7CvC9JKVgQBSpgqeocWNmLhWU8+3TQKhmUwXZBW4/aEIlQBnY+03C59H9APO4XRGyZSKETmkDunkIF1+PbRlAzfv/Od+S0TYDuB7qHLBNXaWApnbm4Ue33YNi25Q/5S7P8yBXv8ftd7oAMN4fCn8gs4AciKo/Tc89WQ8D2aSap1umOrXqIjr3rINVUL6WGnOqK7vI5yJU+AkEWT+f1Dd9gzvnm5Wvwk/AkVgIud9ccEAAPhRWrtqIRzn1M5ly/0ooU2+taRhXyH5ZOXxFsjUxFjOA4EjFxiQtkqklzzaQCbZBfQtYH26bsLmKw2hYsVkx6msz9RG4We6m5i/lfLqz/S7xJhpDCAcrMqtLAvgYhc8OC+CpPEn5n//g3WKfatQ2OCS0L4+LZTO/VMu2u++WBaCLE+FgWFViB01pZkjKIHJyO88Cwpo4AkdyDIbiFqNdGHu661wf/1uKdPEp+i8dy4IzOrERR1WaaL3NFUpsyHlQZKCiQY2syrpNp0W9dhv85hUpq4MArNG5HIar+qTEMGX+hfPrjH5SFXKptO2mL13AX22mCkHNu1vHmLHIf5j7qpILJMDjEvRfWjpWW4fz+UaL1dCU468b0obZldh629xOdzcJOlGkrJL+c30qLK+v18oh+tvKTYrUcLA5LjH2vkG3O76VLd9JJz6A58LQ19N0oHIUm9y4xwL7VF7YHvmO/jI3WEy4DRZq6m1wxfNG7IGIUdTyGm","layer_level":2},{"id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Core Services","description":"core-services","prompt":"Create comprehensive documentation for the core services that power the Dynamic Pterodactyl extension. Detail each service's responsibilities, methods, and interdependencies. Document ResourceCalculationService for real-time Pterodactyl API integration and availability calculations, NodeSelectionService for intelligent best-fit algorithms, ReservationService for transactional reservation management with TTL handling, AlertService for capacity monitoring and notifications, ConfigOptionSetupService for slider configuration management, and SliderConfigReaderService for reading dynamic slider metadata. Include method signatures, parameters, return values, and error handling patterns. Provide code examples demonstrating common usage patterns and integration points with other services.","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/NodeSelectionService.php,Services/ReservationService.php,Services/AlertService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00","raw_data":"WikiEncrypted:E6mVXkQswlRvkiQNYg+8QdJV5H7+P766fkAKo9Uu1PIGDAtCUIuHkv5CKML8sQD+mosOR7cidXxIHXBCLPKdxSuGqJUd/fhRezo9qVbsjKgtDp1U72lHHcqopLEHdp5woxfIy1+viva2zvZZcW18EIff/qUMiQE2Z3uaA8y9760OQHh8ry+DQa26peVFQyuhZem0E2KnMVNdYTIkylW5GiHAP6XTXzU96lhoRV3ilGeYO5Fnapx4uo2BLRe+aW7Yx767ojfarfuTFFIINodL5/0rL1toA1pCVQyjF3L0aHNcgK9m7ltmy2qYd/JZE0lr3GG/vjiVuptvL554DOaDpZ7+u7EdanW2s/+8Azhk+Tmw7wHsosS6oeWGXOv/kAgTQXuTqU34KK0lW3UjRxXIaZU1nVDxwnTw2aB97evyhbIZ7iwGWsWwmwEsQxhJgT4TTsPWdXLeJzlPQjEYtSHOeWYWPlH993A0PoqaJeEPX88Kv0Ii3zncFE3qgu0G3BB0r4EA5g9z/l7xv5fO5ZoH7H/LGZWgoeXwqQZ1JCrhMmyzVjiQlLSo5p+lXG+nsNCpsy619Y5XEpLgMyeN2VZm7sq4aONODYuqrZC5VGNs5LuLfGBNtCu5j/NiYMtF1O2tWrGg7AglOPisS3Ay91CncdO2RfcCmtycXR3fi9fZgc6Cg3umfyPQ9tjzXCjh99L5/zP5GE5iQ0eBBcP4SgmvBfrl8aXMlRh+tZDRiqlKT01pTYWrfab/qkXwqYW9mv3n2J+ChqlGP27sIrghSzRaf7HO2Pt+Y7W+awmfKwL7358JH/6roJ1Q/zrDTEJvMussWu9bMsySBaP+iTBngzHxaZeuu16c517NOgaettP1HHXw8nsEbqOJRI6IllE1tOmKXNOfPoeKzMiB+G/IVjpB1T8v67fdm0rx0zuqVp1rrtYf0Z0RFkqcyWzU0la0qW/1pmxyNXVFQquJ55gHnBUcRaCgqBCN5Cj2MHkiTFZWtEYISLvL/s8R6uFaELg2Z5dkEVleXq6fCxwhJQj+jT+ocG37haKtZNMixWUMjvt6KJ4QyOL6F/QtxvNWYHFK7oPE/Ef6mM9XWWHPolhEne8l3RPH4kb1hR6JuMGL6HK9jr9WwoOKGKdz5oqp3ycBse+2V96LJ6Ng+pxSwIq0rIiQPuBi9jNOxr4ESt+dLKdtJVbXJ7eL6YrJJ+bHHf9yMykDiQso1uKoPVTH5guDmzmxVlvildUSYguOK28iDNdJT+5j/5UIo9voGFHkoZE12QRikPiKRYhqABpauZaBHIuzRU+O9LcEIZUJkOprqpbkJ2p/yR1dAzgjYC0LPJkJtWEXes31T9/PkRr1Dbv/tu3HUJwj5V6sBPyXq+Me9TmJwvHLryKlOASJGHQVjszyI7Ee8WROLpKbG2UKnYVmSTtgxuXxwwRrQ2KXLbovkv2HfcOAgA3krYqptAjYCu111MGD504JaVmVy3VRIdH9BJ5aCaGlvMkDEW+afBaXchyfH4CEaNkFSEkUf4g+35lSOehX4YnjXBAqgdrX9GyN1dEVe6lreI9XZOAPXA9qkj5aXLyoXJ6hYAsN/HlZyr/w9bjJlupGb+hrl3AOzQKXnxxnjwtcvojma0Ncaq/4aTN3M7LvEw3o6vbHho52PTVyCbCAOhC7H660JB77mNqTTfi/32fq64P8m8OOTB+NdK7Ousw2271oYMmZhhXL05ZIMSTPwlSyTrMasUzYBtM96QaOdX8OwYLPekaMOATMSk8YhF8RUqLSGB+RyM70gpPa0lA4canCIkHGWhM2jhmschJpy3Be99E07I4d0Bbn4G/6Ah5h7fuX0mZ2jlpeyQ9YjQZA"},{"id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Service Layer Design","description":"service-layer-design","prompt":"Create architectural documentation for the service-oriented design that encapsulates business logic. Describe how services like ResourceCalculationService, ReservationService, and NodeSelectionService provide clear separation between API controllers and data access layers. Document the service composition patterns, dependency injection usage, and how services coordinate with each other to implement complex workflows. Explain the design principles behind service boundaries, such as keeping Pterodactyl API calls isolated in ResourceCalculationService and reservation logic contained in ReservationService. Include examples of how services handle errors, transactions, and external API failures gracefully.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":2,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/NodeSelectionService.php,02-SERVICES.md","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00","raw_data":"WikiEncrypted:vMsgMax61wW2sTWhXd8DH6aw07pkg2+eyIqOXpXxP0eTEeN6IKKJT4E8yhRJYWTqjspbiPhxSN6D9Pz+vR47nQ0fddxBM+CMIbN3b0al1/8BkDrHfpKECzGon6hVLko3FY3K8WcPZiJxwmWAHyfzgwYhirIwB3W9pd6SVMhT4qEGidO9s1tDtLvNKYK7rouBlY7gg90yIHZef5GrCuZDz4q2aaJWomaFeCXun9RMMG4BmHnAJ9lckOkl/5akjoCJMlxXNFMRzSEnTKIqwXAR+wuaaXUWwgfaNy6xQMvhpHBEaruQH8FZ5F6QIdiI3qB3vZ7wZOJy2eZOjVEvCfd0b36ade2L3O/udL/qNjlwc5qj3amRZHjvPFvu+aWvxfHRSFJDkQBnpDwBW6xPTipFd9l9q2EEK/hY9iLCid8l3Fy9tp3u0vl8NDGssSpn+UKyA8aY7ydb4yzUBjpll2cJ6VuqPiqmInHpjOkp144yZUGKK/BDf/JIHUosDs51slr9kJJlL0uulhT8qpU4W7p+R9OXlEH6WFg8w4oVGXcnSpDchXqjeWlVBL6ahNocGdHEMzXSWw7bJS2+kuBlV/GXg0uE5S6xtV+u57sBn9S9ITtrx7gMhL0gXBefdsxGxErkWgqvQqMAmxssQ3Fv5txeqUT8MjN9iEraOTzgnDsU/4j2/1jDr//piWW1ZAvMlSEqFuGod0Jk9Z/q9s6Lz3zRU3c0fs5F6DtvNZUSGLxkv/dVNNsED7yukiYdhDrZPY0nMYr4zvY/Nks1uAPwEkkhZzJTe04WPsKz0uzHmy+5+EIT3yXx/HIy7F3HMFNtsV4vgZfHaysaTLuKvVeyL/sP6UBJ1G3tO6U+FYqBc9ieW9hU8WkG0pxkt3McrjgDfYR5iEwrrEi6vE6P/7rxuAs4/MQkgBU8zvmbCDa2M4FHvNmkptIdoCMh0h8ugbCnJmV5jDTT0/uFubU9eMO5M8UoSTQ/m97N3vS9En0wTW03AUY8rwrYArMq3zjkQJQkbd5tHzJo0ctalfzKQ9ekPk/mBE/7x36stupE3x8Mhp5MGmF33extBCIqh2HoYDdL7eGVgeOQT5DxKfy8TCb7styhM8AQ9Vnyp6nNQC561Y/aj/046QzqUYAZn2TAKzmf9Mn2AuQkRUFbOi/Q1ugzwM68mDb+DI4vDhH5N/f52EAIyaLtA84UMBuXAztx6UV2X4Ygp9dgiXwcsjVmZUrNvgDZs17jBw9TpD+G3TG2UgFwhTzBkJPITprZ18oi8+XOtbNAwGmK/pCsqgpldVjahS+Dw6LWsLtgOS80ShvbeZjls0X3Gv1Fb9B5WwibhKvCAXk+SdZsZfvO/xE/k0Ho8LsdzeMKpn/QMEZuW3IjG/1kXQTElHewlhtgRGDBHphxTQ7V1reUQDwNNM5MJFN6wIxLxyOUOHEqu7NE9X37Gc49zYzMuRx1D4ve4NGxfgyvT7ToKI8WbMX8x2vtqTkVKyzmHlEwmHZPFGec1gNQGnXIP37QaFZrjeTt3uI3qHAbywZs3PnV292hNv9/8UQ34nyftxdrgFP6Ru04x9S/k9HYa0vMooQ+tLYaTTZ9CoOuUdHt","layer_level":1},{"id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ReservationService","description":"reservation-service","prompt":"Create detailed documentation for the ReservationService that manages the complete lifecycle of resource reservations with strict state transitions and database-level locking. Document the reservation states (pending → confirmed | expired | cancelled), TTL-based expiration handling, and pessimistic database locking with deadlock retry mechanisms. Detail key methods for creating, confirming, cancelling, and extending reservations, including idempotency support through unique tokens. Explain the integration with Paymenter's cart and invoice lifecycle events, transaction handling, and cleanup processes for expired reservations. Include error handling patterns, race condition prevention, and monitoring capabilities for reservation metrics.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":2,"progress_status":"completed","dependent_files":"Services/ReservationService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:39:48.123513+10:00","raw_data":"WikiEncrypted:dAk3XF2xPfdJl9nxiXvxBaJwZsjnZjUgsFHpJYdh2WTsiEd38zI3LZJwvsic+vSlLV79i452hhvBOW4QeoMZpYlQt0pL4IVPlPtQ973Vur0IOPAbnLs+TdT6ZVCHCmsxTO0CHHOn9Mjcw/KGruUDydW0Os943pMNqoP3vcJV1Tec6CzBKOjPoto0RqPpJxQpuFCYzAwxTqVcXjR71+oYYlkYxoKFVvInRrdeiN/u9hNl/v+DRg/LWXDYovUEbEHYqVnKGPjprAuulGCgUVrY/FrjbQuUC20eu/n2u7cPQbtj6P5Fi6/Cux4hTNb+v79W3mUcbDIvx2lAjyU3Cq+QmRWS9dMhQOu35KCF1HZtxGEJba6hMHIAcPRtz0igcnVyyfezjqpTHopCtVK/eGfzRH1getInGPa0tLls0vdw5oUtjNnPNx5EY6RV7tFsu3yTYOFOlyM/D9IQjfmhy+D339J4qSCTHmT7FsjB8kg0BMRuDYhTQfo+mv8dGJj5kOcnzZvdb5bi5sP3H6+Vn61O1NEtj4OYGF3q1lFCLa2k4ZzVfn0p6bLKG9mErTQy+fuJFzW0lLsdfrPPaOKlcd5pFdwb5kTM2uyf+G8+R7kypuf5tvd5WtG14Nj/bUSR3wOyqYU/eTaOwsc5iSFMMwcy7ylnlkHfccHW9O7uc1kG7UFFL1TnJ+DT63tkFQyI3xZHX/wkNVliLl3f/GlXPQUq+EHw4TGuVMhSHDCmuNDPRyYqr95qRcQ64DI/v2ka8JNriLzvKoLlGZF0M9Ra01O2f8ULpkYA2sdTlokxYr8SlLnfx+/yECDDzGu6/8XlaiYnSDpDSE0G5RINWjuMCOHXm0kQUiIainrT2/YYI7cxboxh57TpKWNUVXmqFDefY5Da4kRFi25tfWdI6t5eWWtPmAfOS7bI0S1sr7K5kYnoVUCvMje5QHtuEuhOa+zPSKGO3nK4Tsw+F63K14bYBJFcHfB7zheGWQ7G2HJxZHpZgOjG3f9k2GU41F8nUBfj03NURBbi/D7yDmznMDkKAeRxZccME/XXMSmVyHaddhWHyVR4p/ESqszVe0606gwwWKdTz6BTyB1phAG/zuZv7Pd+l/QXLCVfWDFIyREMpfWWyXjIey0/GxNL5Z+KhRczVPp/5Ni/Uo0C6iPtqlvMguOjywM4C0gs+eJi+Gsen0cBP3JVbufEZEFnQcrVjoDgbSyJJQbfvgqTQaLuwUuBXSoXH6h7w7jjqjUsOASycJ0HK1S7ZMbG20z8p1VJbhIcCmPI06uF6y0jYPUlA9xbIoPx9tQyRUvDRXWpAdt3Uf3b7jnOBFKCgHt9yDE96RnwNLCGLbnsmoovRGkcq+AYWcE7VyRVP/8BIp1G2Y/i9yCYIH00SGm/TbGcVbkgvNcJnXxOG8378mXnquU54RjjjjxV/1Wut2dLY1HjU+qt/Np6f/zqI/a7VOI7ZRJDuSE0rGaRYb6D3XN8Wqm3SKAEH88aspe0Cic8AEW+gcwBiKdjnOI=","layer_level":1},{"id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Reservation Endpoints","description":"reservation-endpoints","prompt":"Create detailed API documentation for reservation management endpoints that handle the checkout reservation lifecycle. Document all four endpoints: POST /api/dynamic-pterodactyl/reservation for creating reservations, GET /api/dynamic-pterodactyl/reservation/{token} for checking status, DELETE /api/dynamic-pterodactyl/reservation/{token} for cancellation, and POST /api/dynamic-pterodactyl/reservation/{token}/extend for extending TTL. Include comprehensive request/response schemas, authentication requirements (web session with checkout middleware), and rate limiting (10 req/min). Provide concrete examples showing the complete reservation lifecycle from creation through confirmation or cancellation. Document the strict reservation state machine (pending → confirmed | expired | cancelled) and explain why the 'released' state was removed. Include error handling for expired reservations, database locking conflicts, and Pterodactyl API failures. Address security considerations including token-based access control and idempotency support.","parent_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","order":2,"progress_status":"completed","dependent_files":"Http/Controllers/Api/ReservationController.php,routes/api.php","gmt_create":"2026-08-14T18:30:20.6998408+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00","raw_data":"WikiEncrypted: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","layer_level":2},{"id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Configurations Table","description":"alert-configurations","prompt":"Create comprehensive data model documentation for the alert configurations table. Detail the schema for capacity monitoring thresholds, notification preferences, and alert channel settings. Document field definitions for threshold values, notification methods, cooldown periods, and configuration scopes. Explain how alert configurations integrate with the alerting system, including trigger conditions, notification delivery, and configuration validation. Include examples of typical alert setups, threshold configurations, and integration with external notification channels. Document the observer pattern implementation and automatic validation of alert configurations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":2,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/AlertConfig.php","gmt_create":"2026-08-14T18:30:21.2682504+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJmLE3o73kryJ+YgkeKKScyLdQq3hxQJnBYvKCfoqSit/bePecpmgpDI9GqpvLlVQ9LIs7lmEV+CCTkpghG+gyLK/O4ewPhJmt5BINAFHKXFHIFOYj55taqoO5+1x/ppZu2HHku9ZZoXXq0CsZ41WwKL0UfXfM//JrSnfCxv9+vBrs2+0eFbNyzEP76TdV4VqF7+tC2O03zgvn3Agc0zhjAnVOWGM+FQhBq+pbx898bWdFoDfYbPdBkGrOHeqEVl51VdAaVMpJbx58m9db60fqr7DxQRnpuL73ShnCuzb6vD6sAXkF5f7OtvM+JJxyTLEQyRxkYm7WAzZ76VfCW8MswNJzmH0rxe7jfGiHDpRJgkk3ay8vTlYKYy3MvASpAk4ffsZpSTjzIcF5aOiD8MjID54dNWqTpL6g/PciOfIsSBvrD8UlcJutHP6ZSfCFDxBOyH1Mqd2jNNuiccleEBeQ0AswhBvjZqE2JCaqH6p+nibP8nKQkfxaYik0YORmlkufYNGYhqxF/hA9hdIKPow5qsHpeztoEplhVuogzfhplQSXwXy1yCPJjW1CkuRDL2ErtDyOAvDqcYC7+r5sGpAOYItYn7zEq2XvxaUhvVuHbR50pKluLdd8ggFrf9+ryZu2Hxv5GoL/zbib1oke2h+RJ0A+cGmH4M1ZLDY3KoSFcd+6u/ASHlTbT19imwE7F19Yuwzo+o6y77j+HH9dnAa1MI8tGRQYCWQ2UI/DkEawmN+2devybDFtfA/ZVrLoTBjW2f4709bxfulvNObwv3NYP5OUVKl6tx0gECW//bbfgvWpHrZp7djAA8AarRPUUVd6iYxo06uFF5C0vaI61IAgmLpgK+PRYSFm47ehoDqMvbXQ1tnO4EKi7gjqlhETVBmCHLLyUUA8R5doF5uG/WvTIjeB3qLQtZcBONbH9OilkoI2ZEfPi4b9EJ06dEVLZjL9aw5AEQCtuKJmKV8160iBi0fJ9udbqRPj2b5Q3+EFDQTOyqdmGPhah0OwpgjFP3ovJZCcDDEQrIUmkX6Y8Js5mCIZ1S6YB6cl6TslKeEwJw5+QyKrdDrCoPYXSvOpY/YxrTlHXqFEs0Lp4Y4I6UoYaeo5nan0IpBG+tP8aqxFh9+hS+7uVQrfD52v4uuUcbrRazh+1NEiyiaU+SA3uttPm57EQ189abNw5DnqCmOE6a4DKQFD1BiZtNNCYQSZLds6xuveWcO/5xHbhthKGgqZuEC36R2yuAP/U6tb/4RaU1R2zqljSICpOYeYbJurXPFeOawdeLmdpgTonQwCxJS6UzUfoxMaTdyJG92xMkaz00RrjPgem5GdYkY6YyVCYbyM0+V6PWfey4PdIm9vaEZuxwX/Ea99BCcg0wlLazXJXj1MTq+Kh6mURrTI6xECRrOwy6n40RfXhK89GOLua4jKBaqOpjcxMu4u6OinE+T8QmOqLpKKtIubkNcD2YXh2KBgiB619vhmVion6NhX+tRjOI=","layer_level":1},{"id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Node Selection Service","description":"node-selection-service","prompt":"Create detailed documentation for the NodeSelectionService that implements the weighted best-fit algorithm for optimal resource allocation across Pterodactyl nodes. Explain the scoring system where memory headroom contributes 50% weight, disk headroom 35%, and CPU headroom 15% to determine the best node for each reservation. Document how the service evaluates available resources against reservation requirements while considering maintenance modes and node constraints. Detail the algorithm's approach to balancing load distribution and avoiding hotspots. Include examples of how the service handles edge cases like insufficient capacity, multiple qualifying nodes, and dynamic resource changes. Explain the integration with ResourceCalculationService for real-time availability data and how selection decisions are made based on current cluster state rather than historical patterns.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":2,"progress_status":"completed","dependent_files":"Services/NodeSelectionService.php","gmt_create":"2026-08-14T18:30:37.1505482+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00","raw_data":"WikiEncrypted:N4PYxZ6FptJ+DLbD6d4AOREdNi1pjOdSwyX0v9JiiPXdgki5dhSZTMx3j6qMo9QxqT5NiHF27e6lgcDdk++lISTpbPUEQ3mLpq8U8ytrYb4/PPV8XbY9b9K5aJ1Odxpapk+xuDFRZitY334Oa3oc6vidZq3psTtfb+RIUSo+WJMKHSui9quFIP16P5TFBT9gIJTDNBqhF35KnSs7KUxBC0Bmr3pXuk98YvfOoi7BGIUslehSowW3Xsf2L+G3h3Wv08vYM0by7w+V4EPcdfE2dwlthpWqs2M1S8WQq0YgMHVsVcooXJETScu5gQ7Mbmp/ST46BFo372dnMqEZguyyNOX1Gur6xFSEfP/ZYsgDP/ZnP491mMzuL9sL17k0OIMDSjPuqqhBtXWNeeRIHWoa+F+/MopE8GZAwBUuaqpka7XtLWwo29CyJWLOqJlhuDCPeQng3iSWayQNszXQMCTXkWpGlU2hsSr8aM6zMBAXaKSg1k5QSsVWSFw7L3srkpWdzJOiuWXgE1wmp3dicOcAYc8rBqfNBssUewt97RMy4beeMSjhd04YNwCqNoDfOh64IjfmsROuJn5GRf8A9Gde0JXd3V2Mjvwk7xqJCpHhx9FdqnMo79mFMnIDMxmEemdZEbsEZd8HBnDgyw+d88P/7uMv4rLufFKPp5VMspJenZkdM0YtFy2tJhkqinOCB2cCn6sWg9+q3KoXvwKiO6G7Ntrv3WFn7aDjJ+25+wckpiMFOemUP14dR2fsXmGQBQiEJBnDXEu16aVxVmVvF/pU7K/AdBbzWnGMn6S7p5/a2r/CQTf93aLxiAIeIrDz8i/7cL2BPOvoJS9j6WMmkuwLAPIHkk/GSKBf7jkQblnlbZlkxxMN0aaJDqEMbMpQZnb4xG7yDrxtbzA0oS5x4U8sFEfO55WGKBPhkAYQ3Dt180ITkAKP/71hW2rseX24wRAhoS7rlAGGdopVbb3KNEZW77tGutaQy8TzQ6aw5CEavGc8hFdifkDCBvGqgCR0lS3DzW4gtfFDE+VTdSEM7L0ODanaqKC+QkBLU1e5HaRZYQ6Ky5gOKzuVPrIJFaZ2YfziMfZc60Sn8/ExjKsRwcifNirXUmBIQgLXt04BDTPl1Bb0voxmOOLfJh/7mU22y+BkxPWN1fzZXQqkBpYBRSohvE+Cj1cEi6tRFBpzkZyC9I1ro/wTi2ymb2sU7r1ml3DYsh0MwqQAjg25wxes8WxRu3v4qd9G5+3JNbTGHKH3R1qmtCKG1TRwibSGrm/OhQY0sLXL/R4P4EoX0P6WgTwORNJPmi+Q2O3LqYBhUOjsLdF4P5UMy6BOrZbA5MJGCxEtXbj2SmA+qAVrrn8nzmiWn/Z3WXTJG5+7B6WtngDgcmKccIi3O6jBP/hdYqKqdhtFsoS603mZ5YeAtli/qbqg+zOfCK3PDX/B7Ku41IVOfOWFdNrXwlYVHgfTo7b1om7UDL8fNHEHtHrSowe6sbDSl2PVCmLNR1M6C4DcIA4ymvXFXjf8GBW7f0tiz5oOMMvpqjX4nNELtaZPDHiiYf8l/TY7ot6PMdBJ+B43eCQLePMGCeQWokhCUuUHY/Ve/NVbemj6E/c3Ytr+g370CSgQOr5N+kNI+RGv2CyMd9zBP3vJGIDg/u8Q/GZwRT6HluZEiORghQ1JyG2wZXcWsmpn2KecPRD39Pesq3reHXo8ceC1vkLArqi+PXQMAZfakJ4p","layer_level":2},{"id":"bb865521-1431-40fe-8fdd-d248c151919e","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event Registration and Configuration","description":"event-registration","prompt":"Create documentation for event system configuration and registration within the Dynamic Pterodactyl extension. Detail how events are registered in the boot() method using Laravel's Event facade, including the mapping between Paymenter core events and custom listeners. Document the extension's integration with Paymenter's event system and how it extends existing functionality without conflicts. Explain custom event creation patterns for alert delivery failures and other domain-specific scenarios. Include configuration examples and best practices for event-driven architecture in extensions.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":2,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Events/AlertDeliveryFailed.php","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+imxxp9gLOp7oepygJU4+6Llw6GR/aCSW49kVRbjAbbfLqA70dIewPOXhc8h++Q7Cyrs/QsWF6aUW47+Yx5gGCPo17twDAhM/MD3vl2uTVHPZfS45uCqIv7PlxrlhGKjsUAFE33mf5jLeq8XedXLmfZgV668S1Fk2DHiluv7Y17jr2UqgQLCPneRzOxQB7TKJuOcjPWUUIQMpdQMs2Hn8gludyP0FyNnFDF3acXSSwBye1KxfU7sqz+mxHk9Yv0Ns7aSurVCaRNr1/sAP+9sVeGezazrjN/7sgN7t162IqKBw/lUxDvr+VZvYa88/cRlvJhF6KgM1ljlXhvAleZtYxqqNZCjAKtGEz+Be4cPXxIX72TQLalHxLeLvl2kGGmHriiFYrWdiISTkdlva/iol4F6Ef6fBjyI8Xplyv2tKmLU6IvoVRQKqpAMCg9XoiNVPTg9vGh98+26P0JR9sE+xQwlIZSa/ibhHoymr4/gf+fWIyyEvLzDNa6TeJJWNAseS+ngzCvYP2QcC+BkDcliqNSI2gBoOSU6tiopaFe5qpzYSe1zLwfRfMLx6mkdH9uySaVPNEuW+Uyh4bRSv6SUBSRvtGMg2bRM5CNhAr58LNTIHdGbfP+kRnU7CZYpYxGlyhqWiOcAANj9ecQElQ/080qk+7QXRjxx609KevAVtmyGX1OWqMP48+9TZQ8KsxiqnjiiSWTWwXeNTLZPQ5EUaMf2O6NTLHm0d/sKQHGlw76+uCj0bYwKBxQE8Acfx9k5BhuWsz6i8gpPWZ4IXqfrjk0RIaW0j0wT1VwIua07Krn4EGSaXUTX6sKfLlmQHijjqBQrMwlSBOPjS9Pa8YmPzS5FVe0dW6fyaHXyRncbI/F5jGVSEE1noqxX/FtCzO96Roht2NvCI33xsZNwXLDCJXApWvuXfEmQIxlAaLLj4OG8TOx8W6DKn3N3UdQ6Z7WaYgF8akU0AZuPOhtKHXxRdDWcRhIfXAfmiimetXCEuVmwWN8hOYva0UudiL3SvN74SMV3/CnAoYphdM9uJjvmX/c=","layer_level":2},{"id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"API Reference","description":"api-reference","prompt":"Create comprehensive API documentation for all RESTful endpoints exposed by the Dynamic Pterodactyl extension. Document public API endpoints for availability checking, pricing calculation, and reservation management including HTTP methods, URL patterns, request/response schemas, and authentication requirements. Cover admin API endpoints for administrative operations like capacity monitoring and reservation management. Include detailed parameter specifications, response formats, error codes, and rate limiting information. Provide concrete request/response examples for common use cases, client implementation guidelines, and security considerations. Document the distinction between customer-facing endpoints that only expose aggregate data versus admin-only node-level details.","order":3,"progress_status":"completed","dependent_files":"routes/api.php,Http/Controllers/Api/AvailabilityController.php,Http/Controllers/Api/PricingController.php,Http/Controllers/Api/ReservationController.php,Http/Controllers/Api/Admin/AdminCapacityController.php,Http/Controllers/Api/Admin/AdminReservationController.php,03-API.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:07.2555848+10:00","raw_data":"WikiEncrypted:C34GewOyK1SlumqKiPsSg+WPNa2UHH7yP2PPjE4/OPlAbu3AvGLNlwH2YbJEsK2ZFah4wHB5r1ikrL2gZxnF1Nn57fAnwhvy+SLzHtydtchPCXOmIuzxruToPm6Xd9PRtGMqZYPr99N8Dff7Wet0bzOBKeAAcYwLuRIMu8wV3+tBGjN8rZVNLnUAXs2X8elnklt+pWvXhH7Lot1U/VTnmmPuuzt/9RgwloJHCX1PFFC5DMjIXsAqr+IHB79ukVc8/OocFqYwz3197g2fugTc2EACI5kR+lgALYTBVypdBN7dzBA7BWDGv+ka7bcfaNeCJAMR+nYwvR/05wepx8Sfgd/yzrdBih68cMl6bLtoyw6EyycFnk1d6PLIGmg0hm/eJQMBfC1hP/EeUOGp9vpN/0Ufm9/DvIMhp5evoBjvAzzrxyVYHK3e97kBKj0SM5FwAaQJ69x1sjLObgiIIlFRUB4sjQ8O9el8uaG9ChyFVFnNv4i6yCyr+Vk7DmJ2cb1epnNj3HMj0xCN4M12D/dQHFNDYFbERU+bdaYrpukKPiwbt71LjAaQmJh8s3zY2eWljsGmpKMhh6HrVwctHTI3ptnKN75C92Ik80Qn1vjAFPsZx2D+bAOIl4KJOTe1+G1SkPkR2dmJz4Iue24kqEbye6NaTQFEG9N/XFzRs+f3ALfzyBhE+uPApEe8iY6BmB+mL/GKUbXiNJY8wUFbr3FxZa51up6jh368OCGAIGpHKs1fTxexEd+BYOPZCKhmz6ujxk2rjsLweJOlwrdWMaJnvVIxJYetiWIINq0JGRAgcNbT/EljDQB6ifHUVLdRaxv9qRuEThRHMkWekS8YwU2c3s4naKkYgFOx/HM+6VIOjWJkvzBPUgvT81WI+H7rDUMyZQHg1uPBgGRTmjZr/o1vQrkPAylajo+XKJd3RBetjU0gWt/Ts49S5Ppb73RZHAoj5XJZzKA6nHpeoxEbHU7eRWqdQFPNnlKqSCIz6zsHNvVddT8QpcQFqNkh3hA7sBUN7iRHwqqYBWh49BY3yeo9u+I359bZmI06Hm1a3vmmM7ULtIpk4F1+v+kGrril3JqKevzsvl5KZdEBrV7jSHtDY9jP7qQuSD9mZUXe9TCdd9UHnVJQry4UfDekADvlsXASgwPLRSVNDuzrglHRhW4J5pMX3BMlEMjs3KtDseFrHvQxXsI4lDAC8D7H9sl6VhsSy2QndNpguicOhLPHcSFVS36yYUp8uTKt62g5DQIiJw4CNSTFio9elMOaqT/y5hGpLHAow80pUl1E/8JZIt2fdv9yQFwEOK+SS7jAWuTh0bLlznwd8YYQHcz86HVrdsyyj/tYH4jP0PoS6aBYe+xa/YgHdTRCRFXM0GvL1L1N89uJSEk75sn5QYCDs21Pms+Yykvb606j/zyZq4DYzqYQyvXY3LUDt79VX0ZEEnez3PvlHlmD1O4vqWMaI1AEVbgTHOx9VM+ElqyU1cjj6yvrDqHTCfVOZRVvhrt3WmaP1Sf5rhpqFBIrAifNXtbI80cmPmtBjuy0HgwsuHKzwQgr+XQJEO/6MloqpGxTl/FeE2SLDj4nTgTAgggJDsbd+TpS7FDg59pmXtmga1jSw+/Zb0XZb0tNTmn2iiMqgJd3H1y+Y8x1PbHPsX22SDeVK/lJRtrf8Rx/nnKTF9hp9S6MQg+MXOzKBuvaBa375GA5VzbBylobAi5jKHA4znfy6vnX5kMTRwmaMjInarW4PKLunNOSUM3CSGz9ke8jna7FT4hSQb7X90Y5nmX0EoAwDyds/0m2z0YTiILgqy4mNz/m3pih33FMY6H4uReybGmcMsHwieJkfRNO8XPM3/bYDC5KMQ8VNPlzjepYXroN8qN3SA=="},{"id":"8e2180ce-6afc-4199-856d-14944750075c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Real-Time Integration Strategy","description":"real-time-integration","prompt":"Develop detailed content for the real-time integration strategy with Pterodactyl panel API. Explain the architectural decision to never cache Pterodactyl API responses and always fetch current utilization data directly. Document how ResourceCalculationService::buildClusterSnapshot() batches API calls efficiently while maintaining accuracy. Detail the error handling strategies for API timeouts, authentication failures, and rate limiting. Include performance considerations such as connection pooling, request batching, and timeout configurations. Address monitoring and logging approaches for tracking API call success rates and response times.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":3,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Http/Controllers/Api/AvailabilityController.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:40:38.6189761+10:00","raw_data":"WikiEncrypted:a46miLh4B5C16RNAKII6IEKLw0MqC6h0PiMwF3Ka7Ij2OPHaScMUS59vSqkWUUgrkKLVBTUU8zoSA2vaNuZ2rf2OJdfGeO3VgrgnuSh7Y9mbKNPBn+TGvWcO5AnaXJB2EdUDr8X7KvdhK80ezYaASqUGUIhpeqR149c9mnFscepyWgx2Ek8KTSwFVC9MKhJosEyGJrn7YyVGvQGDCKSsh9Cfc2/hlpa90xca4Gu3QNSCVQnZff4bdk5zz0to7cQ+zfpx67WTW/CodBDhmMS03I0uTZPJE7AJP1ERvmnNcXmsXkbkTIn6Jaz4zHR0znIguYIevPlUoS7IXDtfxhXftbs+dzDSv6d5v6serP9dhVRERBMS08vKVQQW4aSOXk5hWd1dxoNsWCjPokAE1DfcYWqwH6aJyFWiGAMnpgRi9K/ONKBTwp7DYJ1dc9L1gguGYAzl/fKKPJA4PM9rpfaw6qMRrxdSi+f+cOC+WNiXDQJH2XFy1L6VZ+FAp8p0yd7blXU+U4BcEWn70ZZKe8EhyDkkmDfOBYjEJM3cKt+oEvHp/WAwoaASh+fKHOiIgu0d0Ftj6vC9ACsxKybfZ7JnYgbbtO97+eV0hg79n9Dpc42WRdPi+7fZjP0ZycDvxlfhRXage94By1V+FNrcn1xs5USrhdX2GCWwTbKuo34IOCI+k+fJl4+OMGjYuv/To3BJW14XCaXe0Vc8+GB7p5QyIm6B6fsg6itIUhRuxWEcLtizsBLDkPPBfCfackzY8FefHCuq+16ZiXSfAmDwALKTtOBO9+lO2ASRDOZP6W3Bfx/dmEngHDG930BrKfyjOiU1d+Dj9C/KTGmVedsjEPE+mFsNeqGzUx1wcHlUXuIR2MoS/IkE6pAfKQFpuad+LK1zYsBeiXaCDtpDiG1T3FbbX/wlv0E1MM06Z2uVIco/K4JhN2h53sPXy5CasAiPwd+gP/tBZ4P8/RZjCnjvRJFRGAS/an5RflBLv0Um/6ZYLty6ydTuBe2zA9vspNAJbs35huP2iTnJyos7IYxMOCVI0rsp6911a8m3QVgqExQt10m1F5K7xRttnWPk0iBVFitXP8UzsDl4gmWXBvtl5+kdNtO/FTX/LMk0VXgqkSc2hfnQgLSNO8Q+M+Q2P+UsZSLgQOUZdMC+fY5jleVxoP01Zq3Ny/88qUYkKwFqKY0URwyZXfLUrUReHlG6MnFCB9VepBgaTEijhxARQFpyXl7ZKAnxY+GwFSISTsHHvJzWY4JhYfcdWqbhFUVyycwgVkNHh95kj5HTjK/CFqgeY8hT0uovksN7qSUIC4uod8qI5X03bIV5vfdg/6Usx2DbFNZzZWfdwj/3RrX/XTI7/1qEMly4jFw76Uu2HwZE0F0cK24=","layer_level":1},{"id":"46b9fc6e-218d-4212-a930-0fc7713261c8","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"AlertService","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that provides capacity monitoring and notification dispatch functionality. Document alert configuration management, threshold monitoring, cooldown period implementation, and notification channel integration (email and webhooks). Detail methods for checking capacity thresholds, sending alerts, tracking delivery status, and handling delivery failures. Explain the alert scheduling mechanism, rate limiting to prevent notification spam, and the integration with the audit logging system. Include configuration options for different alert types, custom notification channels, and monitoring dashboard integration.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:41:26.6868225+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumFsNsqmOR9Y1fz915yV8RIIIcnGt9luzUNB5Rts+iylnavxhY1AgxdZiyE17XzAFkcDSvNL4Xq0i+P8W084sXyyLi/9f2viIbprKi0+6/9b+L/MgNMk2z4KexjoSI5nKpqx6N95tWQc7xornaWWhIj4VvUm5KzjRo+naM8WzmBZV7jryANDyUDHgelPd9XGEYhm0CeTnnt+sSu3WyMcH81ukC1DWlY3kLa1hWp41z7SfPudp1BwQWg9FGrkFy5SbxGhjbkPE308IBvsxDnrxDkT/AASdvk51kd1eXaMFprTEvNbMKTvejQGqIQfi7oAFDoTIsPSpYJFMjjLRzaDP3xabUfj9Q4419Ale3z8SWX3cnDKoApAQq09BI8wHLL+sxUtAyuAk0Z9G2AWoW4aYzxOx2JH5MMxpJSS+Tz8IyOr4aq10oIirutHVrVgtxiJuc6KaPOpXEwqC/RnLlOza8+x+Jvt2J+Y39P8QPvLdxQIze6N7dPNLowvWczs5dsRlVR5y1x0tBjNU4NGfZ8WiIDo0qPjvvkCzhgTwm1F0/yoE+iZ6X2stVI1VK2i9L3Fpl/2iNQi54nkLGmWY/4XY89BEFmQJx0RqmFlTfrrEXP2SlvGx5SX9SMzVzI5qBkyzxonyCB8DHl59dIL8Yy/WDP4N/VF5aL2TFDrM2Ab2TGLSG5MDIzMZo0lAYmeSHj5VJmvRJ1RGeDByCXhp+Z+ME9s/XW2Yikd68rCgIMG86Pp+gCM8JGVvs7plR7lBZLwkFKsIe7Fz+jFNEr1bF+bIPnUr4FKPeAKIN3OxoxINWXzoDPlCLBHeAZanWfWwqyzR+J7IUE3hyahLtZ808XPSJTtHsRkPZlhpRS8yqbnTMk2nmwsW0AHAt9qrI/a3s1b6fhu7NUwxf8JhYYr0O2TkYJcGO8wp78xDX4Gd3kak9LbdJh9S/Q1HjFm6Jp7FzWRusfm3WH9WkcoADoG5PiLtL3uDwWiXBnsadTtadBT1wKkQr3OjNwJjW4qoM3knH7sm0dsOfNBp1Lz9170Ks+GN1qh3VCXhS0JReKUxLFwVDGfMqkoXYk9pJKUNUG32B9grvwSdBbGvp6Re4o2edK5XZSUzrSCa4woyxpE3oJljPdr0LNy5957Np3DlNHrHBLSF8Ttr+Gg21v+MlO+IrKEyw3CCT+BBlhTk4u8C+7l2142593dhE0YP3BKKFPDLmihsazXHFP/RsQRNWE2zODEak/Ix6Jhjv8cQz2Gi2P4m1CsDVSB8gYLBEIvppaRagXhVGrdgqc9uwEY+vyX6VJX6M11","layer_level":1},{"id":"db81e08e-4803-4640-b5e0-202e80fb914b","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Model Relationships and Eloquent Models","description":"model-relationships","prompt":"Create detailed documentation for Eloquent models and their relationships within the database schema. Document the ResourceReservation model with its relationships to cart items, services, and users, including scope methods and query builders. Explain the AlertConfig model with its observer pattern implementation for automatic validation and configuration management. Detail the AuditLog model and its usage patterns throughout the system. Include examples of common model interactions, relationship queries, and best practices for working with these models. Document any custom scopes, accessors, mutators, and model-level business logic that extends beyond basic CRUD operations.","parent_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","order":3,"progress_status":"completed","dependent_files":"Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,Models/Observers/AlertConfigObserver.php","gmt_create":"2026-08-14T18:30:21.2687638+10:00","gmt_modified":"2026-08-14T18:41:52.684526+10:00","raw_data":"WikiEncrypted:o5cr6Bo4m333A3G+lRdTT1zTwtVRlFzZl51UqVOFJohX4sTIIxVqYCHtRd0t23P389kscTHQTThJhL7w4nQfnwR3RCAxF1nBUIgc+YDRw7/ohisZ7xjn56OLyPO/2hMEOWkhPTvbzOwXZt0LS7HksKWM60RYUDKclPaHZKiDDOP/aNhYGrqETnv1qqqLtRzmMtosNd27nUSf8XuVdYNhxLlNs0GBV3hJccblk2M+M9qR2+bW/8JARAzfCQKg/MuXg+B6muiJYBWVwBQ4GMALlspnfoLawbHDKpJ75lBeGCjT44XltN9ftRwKHBc1QK0wyCHnNVUbdPXOwZm9s+SR7EHEQZujo7KhrLzs1hO9dCeVOtlclovBuiAh3M6/RJvxjmL2+3JeCy9q3oll0xpbyq6pD0hUqUblYDqqfpLa/hCG5qs76yiUAkg+zknJnil4qOZ2nFGmtmcgrxFZCbGU2Fxe5eGyB3VgEVtIYDo95OcGlTMkYNQeNhlH6g+gccab0RmD156Tm3aUg2qsU99rUOiUATmefkuiRZQxT615q4O6MNvvGIkwmd1cH/5wHRQMvf/Fzcm1JtRJPg4rSCA6Gm0kCrEK4kcN2PRANK782ulYb7UwTisvgSaK1l5pRfnxGv2ZMHZv+E93WqF/r0nL/ddriCXKvwowrvTG+KuzT/UYqzsrv8eo4V98dZzYAsh8SMj9bu1byFt1Yh5ZH7ZoGklQRFx8OAeQqYKfMBzsNjW0YzC/JZ9SL7AR+3Sk7YuEQxL4H7OGX+MQHHfkdlkwsS5jCLiR8iBMCZPtbcdH8+9cW+D+j2jTjYgnb/a5Foj8C2Zu6AbAtDIH4QvMVAeof67Ii3efQ6YsY5HYie1kSIuZBQNUbny0q/PxC0m/0YzgV+ynShn1jn8RYuNcZXqLyMX18azcac9KVP0L1LWtPsb8GCURf+RZasftCXxU7H/n1ztgrKn7htSV2h9cPXTrcWJla/l/crT8js9/DN+7MQSVPbGtMS4sH7EJTcqberUn67IjhAf9dElvh3NgA063fr5qAAzWCquB5on5uV99/r+GnfsX+vLqGtUsQhq0erEQ2WySTm9iyRsRjsO5k8XpQ6/MbJ6A4fzmpCgM6A9C22hPVjcV3fWOmgGqcxDl//H/fesJ7vC9eTD3R0IPkZx8sauyONVKPyL5jKjTV2PQ6ZIF9QvM39tywIJxlKkX6oaifeWsUn2kcNq/9S65EWxmeGPLi8e7egxAY2NJmK3h6FEiOC1H8GmVDWQE23MJ7WL3RgRuQgSkaj5FMitdnbGB3oNxh8FnShDACIW1BkJvoXQTY6Aa1z87M0NsvrmEfIMh6kXjGJvUDwpy980oN4rJiYgzHh8NsOsRQ2hManyQaLUnTBOfjpKBZaoC8npXNdf1hWkYe4lQbIALOGxngIiz+ZZPzE7f7LYSIiFSiw+c136k2ahb5GuLg0gIrQv2GqfLnZvNdgj7PY4e6AVZ1C02uToU2IVLPOIw8h/keXkCSWrBbXaRiZe2ea4IJfuAVacOn9KVr31XKso+d3EU/iYJNVdfQ4v6mHSdRi/jFaH/+YPvwNocx2ABs0faFGlDM4waSGRTm6/ZNLsngiMonux6rA==","layer_level":1},{"id":"2c2143bb-a6f1-4903-bbec-853144163068","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Alert Service","description":"alert-service","prompt":"Develop comprehensive documentation for the AlertService that monitors system capacity and dispatches notifications when thresholds are breached. Explain how the service tracks resource utilization across locations and nodes, comparing against configurable alert thresholds defined in AlertConfig models. Document the notification delivery system supporting email and webhook channels, cooldown period management to prevent alert storms, and delivery failure tracking through AlertDeliveryLog. Detail the integration with Paymenter's notification infrastructure and how alerts are triggered during scheduled capacity checks. Include examples of alert configuration scenarios, threshold tuning recommendations, and troubleshooting failed deliveries. Explain the relationship between alert configurations and actual system monitoring, including how the service distinguishes between different types of capacity issues and routes appropriate notifications to relevant stakeholders.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":3,"progress_status":"completed","dependent_files":"Services/AlertService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00","raw_data":"WikiEncrypted:mGloAU9ocPWd9c/n20tiJqx5DSN6YSWNF5+w7wSOumGkxfRPgWKvo9spYjKOgszuk0MLNmFKFcVto5i3bn1a1JriKtvACh1XiJaF3txBGeDnTpOnGI8GVp8dZmpnIguyLKrCGW/X9jZkgbwQbVwEfHRmENV5PlaZSvRfpq1Y36TBE0noLaE5sh0q176aWnStZnBj4K2a4xSmOYGAsv8HbqTmTWvunklLeJaWjs6NfBaUopbzjuehHIDTnfnuutYeOYeXJUjpS5R+1X/olKDhoEP9KIeZQreSHIEpR8VFh5xjHzzgNwO5Omd3makVXkMmwS5bH1hAN9+/UfDHYbVxHO/Wrxv4T9bYCWEdI80EXlm5WvcMwsdXaFNdD/O0MedvlDcDywhModRKFVrD/v1JxoWN+pIMR//8Ryk24kEY8vD7Q+Ko0lPvDRRgM3jtjpUtedhCOT4HyA5UUR42KQ+kYZ/hbOq3SU+iPGhZXRGSX0/mfH9EXycATjrar7+ptDChAOoLsBbNzwtCqTviL+XwwE0fG/mTTM+oKS+tzc8SPMzQnnNnQe5SiZ7vapYaGJ/Y1F3/1RljayqHMiGXsJpEogvAu0YtB+ozWriKQL73gts0QErqjeVZDpKaZlAJypHMUo5tLo8QKpfRPkuFNWsN+dD398a/KxDRB3y4xuO22KOSbA0wLUHX+LUfOLbsmc7V9YZue0GRUpU1QYr2gg2n6ENgO7KkNSIpFP7tlVLaXZJstuHVTJ6bVRhF1vJt/a8GEBvJA5XNUV1X8YBCrFeVSDiYvLN3/g8sdb4lvFkVU9z+OAxnTMiQTOUhzAhadn3pUZatOBH4z5pMrVFlUddc9dWuSB5yzL8Krnl0BOoqhcr9wz1zxZtUzHuYS7gRstc5PvRuH2t8fjaT/5F/b7QpjH33K/TWFvQ6NzfcOA0alBXDFOzxHtKjs5iITPrLZTa5qe44OWeDgiOb1m56En+2v3pR+26yZqNZXuHXw7W4g4a/c9UW7X02Xr3681xPJZe0VHWkfH8XcEqatS+zpOPcEHdLS2AZS7qdEnk0qlZA9IV8bh/sXaTXy2IA94rG0nN8Bg1BuIWUKDX7nOagOtmaaiWe5ddMrsk7lwtqCGTnoP1Uap/OUOcBFW30SqbqlY7SO2/WjIix6MbE4s9A3FOQEubeQXgRMG9MkTmrQWMJ+kATfAoHrufX6bnbiU/u2L2/TCnV4tq7C+82Ew/cW5nP5jjkUcVctQVTsPKutoFLXa2m0au1WpBGTumnt4G+Q5Q4ZMiyeMhpjTFyOvhvRUrlbI9BULjKWNerIvYFEBzoW8BI37AcWDCy6Eza9ZvDBryD+9Mg/AUWgVFiWqrk/kFt7Y3fnxA+LKb7w5eHMEB/dukv1UGuuCSG6YafBZqG4+teiF2AGfG+h9o2xna8JV5FhaQbWAxvd1BOQZX4ThU2/sbwY6Rjt6yOxgVx2AIMAKzGlUFTbKmGdwbgSzoh8cjbyBFNMLkZLDPOKQov1suOnDtKzCaYEc6Z4IgqQC7/2eekocjLQ7Dz8I4Hj1KjpqQrdP3hAUeMbpxD4GoW41VGDlDUQpW+4rheUQoIuDtNTW6IloKthdVEG5SBw8CbDC4cvboP6wbeuz5X6RVmRIcM1wBm86ZJOPSo0F8MprHkzOM+WjypzUBOO3U9VJ2hW3ahYOVZVj4NicoxisCYBWOCfWUYxB0oRiIIyqDs0hZcg/6nqacuMYo6Gl6hCkCTpTsNqW4l4NVPGvHbjrCbWJu9w9HnGq0my8u73AAHUAuX12otrlJ8U1s3swyC0aICg1W5CfWglqfY0bBslnvLyd+rLJAiD7VrIM0RFRXNQ4AAbVm2","layer_level":2},{"id":"632eace8-7d7d-41e6-9c29-2c85e645491d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Complete Checkout Flow Integration","description":"checkout-flow","prompt":"Document the complete checkout flow integration powered by the event-driven architecture. Provide a comprehensive sequence diagram showing the entire customer journey from adding items to cart through service provisioning. Detail each event trigger point, listener execution, and state transitions throughout the process. Explain how the system handles edge cases like cart abandonment, payment failures, and service provisioning errors. Include troubleshooting guides for common checkout flow issues and debugging techniques for event-driven workflows.","parent_id":"2babb181-df9a-4da5-b222-f75f0ec91241","order":3,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/InvoicePaidListener.php,Services/ReservationService.php,04-EVENTS.md","gmt_create":"2026-08-14T18:30:40.3530994+10:00","gmt_modified":"2026-08-14T18:48:16.8368671+10:00","raw_data":"WikiEncrypted:/3r/IgJF/D+DnPujiCpodvoNOiYM3KFsRAB8YlBdu+xb7BS8Uuh3IVK1mpHtXs7mPCNE4VKKRn54TjEfbcpV5ZIJz8TmbubVOJ/dUgIK4mYkS0hMUVvwv5QPe1Q3QC1Q8fbJeJlCF+5/VuoYzz534aZeclwwi5Oue6KbEf/myM+uSYTvEJYOEbyq5PteeU7K/JEP3av8RyGe8WqNIMavK6yZ8dltFKP/GUgUyJOvvC41EQb0wYtEbvqK5cwo8LabsKYcAfpsg93fdSycxCIcCnQ8WFgzRq01kuHfgUsM/IwbM122IbQLHnjcxfxlr9vaxbEH1DdEk2TLPswyJ3UQ5bQzUAJNYKPVBluRcDyzLlT56IxsYWFHN+EdIuJ5LZKC1iR3xddStraJshePes1Z1GO/NKztwAO6hSHIStexDvyorJqyUvbYgSsv8NQ49rhtWfKzdMTU5MxP9r4P4nUh5jjiTOyyEJv1V73K1qDF12wYxV9/ehxaFQWoXpzMmLa+FySGKcm4vBIWSyuhDcKT8a1k1psgylOOJlE0/biddh62HcRl7hL3DuNvICGgfDtQNppNojlNC1LPyRa0o7Mz27sVtzYCKKm1VDlD9VlMACQ04/AkiPRb9mjOqBjNCV42FMS9d/1ctC4H2aY0JprVtKK0dCkYWsfaacA0+ldS94CKeCO1e0jRMT6fLFoIkRSos5qkoRmOU5eury+LOX8kSLKMEgTqHawq6hutANYhMSsJuCiTQXDPnIn8cTEDRaIEUdXXFc2j7zMP3+jrw0fcjE49b3jEsJOE+4NTdbzkc+8sq6sFoBJdvH2Hm4kmvxtiRtNAmy6Wl1V90rQC1js3SvE6J1VK6941VIt9bTWks60R5R9uHMC3jMwbiRe8lb+LqUa2NBIcSrZfHYuTj2iG8jtSGmOLpcwCZStgwNF+WrTi9Bu9OjiZN3qxFH8vgSdyueciKLHypbu/qYCWV3z3HTmt6iRwAFYQpg0L5BCZiqMZM1y8YTTxhLuL4Zh9IXgUrE8tQvJcdKZHVW2oM+Nb0t5Bl/YBldM2Fyfr6Aew9whpbN356+Cr1kRKs1pBky94A550JCDX1oX8/mv6fXBydw==","layer_level":2},{"id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Database Schema","description":"database-schema","prompt":"Create comprehensive data model documentation for all database tables and Eloquent models. Detail the resource reservations table structure with fields for tracking temporary resource holds, TTL expiration, and status transitions. Document the audit logs table for capturing administrative actions and system events. Explain the alert configurations schema for capacity monitoring thresholds and notification preferences. Include entity relationship diagrams, field definitions, data types, constraints, and indexes. Document data validation rules, business logic constraints, and data lifecycle management. Provide examples of common queries, relationships between models, and performance considerations for large datasets.","order":4,"progress_status":"completed","dependent_files":"database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php,database/migrations/2025_01_01_000003_create_ptero_audit_logs_table.php,database/migrations/2025_01_01_000004_create_ptero_alert_configs_table.php,Models/ResourceReservation.php,Models/AlertConfig.php,Models/AuditLog.php,01-DATABASE.md","gmt_create":"2026-08-14T18:29:54.6243105+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00","raw_data":"WikiEncrypted:veTYwq2y4io5qXerCTrkkKY19u2QVJ1rg3+MIy4jIV2G7991jW6cwRmNYXwYpuW5ArhlxyDWCj1MQluATkttNYsoMBDdgKUezQdGDD8+omhNzdnb1qef/N40I3Anr2QwMP3nIUzAIetBWt3asETmzgpUhWqNi0c9/gWDGL6A/YQUM6F58t+gH796VZqdRPXxWuT2pr5G0iutoRLIdprxtMSC+QZHRImcmyRxuoomSfhWYNg9uGlj0l/lCb05MCiDJMEDcZDxLd4fUn8mnozZiZNTTSubVHAZOpJiSi5LB5HxFsVQbCNsNUADnWSR03e9Ks7klVEkvvs6l6dJks23NZJAg9pbH7BTV1igcLixjWxWz0slRxP78BJBbYH8GOkAdRT1dtzdIeCC8aecaU6NvDqi3gVqMard/lFyXVLICVrfiEstzYj8ZsICdnNwIfFlPqqOSsrhU1+YE/NVqp749vMdUf4XZAsaUU4OGYnXalSFAU2pHn2P2bhE6MLibxENIk5MWOVyeBrusuddKOXN4wWJ8au8Yq4jkZdCpuY4kuDz19y7Sf3fXriTh9gdnIrTRlUsD5JxY94KfGJWambQDZNcNtP3t6Ggp/nsKhnRqZBrzMtfYQ4ntzyBW8gjWAuSwblrGF1bdDjQvjKHQkJPIY37D7NoN+ba2PGfg9gXRDoG482XzqjC6l8ClCgavMnoxn3LMTPRg4VYSigxaKHXfUJHbj/1qo1rXakQpSBEjaHWf1L2ufg7ref8zTsvfdEWfpfVX06/4qzl5rC9n3eFeTM/rZJfL17yHRBltESgzj0omjp4Cenb7va/SpJMunvExXDBQDvNRT10jF/oMVSlF+TbecDZ+9hZMnnVhytpEkniOumZWXgwDHJxU3KFYhnvKMFzfp+qPKo8b17TtidoQzQ5GDhkFkNpvB3/XabohBK2ceJfRisPlb40nL9w47tCdDa0jsucJqVLZ6olCXjrmEjL1fjHE/5LSKjI5pLUMJITZV1qG1rtNBdhKRGcd6aJTQqCuoFgJk6CsDWZ4k/8G+uwwIjdOxvdsEdK8AwkOnH/Cj3azhQh0XYo8eo3h8r7qvAXelQR8kK/oiDpjAP82Y5821q0E1Q/g9UJ/xxLu9ScqfBiK8bQxJ0j/+cWNMlyfqScdsefdowAWa9nQJcqH6PR7bT632GGsV5LktkiB+jFYsRsu4NnmKaaiavsSXte83lTWsx3rCiRbDXDp/ukZArS1mqMm3oVzS46EaWRXSZG4zJiaoFh9sHUSPmoPnPB5Ph5QDKWPLG/xPJl+XWY4xhP0pSpiT7uMilGWDNGXHOfQlFUbzxOu1ohusVTWjYAnW3bVkXZ2m6ONRqOs+U7s26t/Ae339JGrEiaO6mcmnLd+OTYvVBup6de+JWs0fGO/i1CQD/8NyoY1C4vUetq3QMiG8R4VceBYJzddNuCu0aSM5yAGF7DF1T8R6yN41LM5P+6B7DGyAiMUD7hJjPJJGFNMwfiLoT1BvG+FR1Ews7eS/hESzkyY1BMfG9Fgcbm2RNFH9i7S+FduOmTn9GF7N4zojNaAL893TmD4k4ICDgVoGISrmzjYLPGjRgnxGFDskHlHjMQegYV136LsflYifyTUxFI1GVuTKmRYo4eeBa9731huIhfsQNa9xFSEE1EP/980lu6g/G8Y+cxM7nRs2wjapYIufIKAsHCwW1Sx9+aqrqxJ40F/YBw2Rt32hVdqvOJRQyyhoqOGsk4Of7bih0kSX3UrgZDL/fngP0/C/GC3vChV9fRmbXpRiW6wKiBGLW9c2m7/GRnwgnCKQlmEbfILmmk4YQMgB9CeNX+zVEIP3ljNws7qOcfrdP5JZuhE5EMDSqOt+x16Cd1GtG27CrIamyc0slol9sB/4GhOao="},{"id":"f3550273-5462-4317-b2c2-6354a1b8c98d","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Data Consistency Model","description":"data-consistency-model","prompt":"Create comprehensive content for the data consistency model ensuring accurate resource allocation. Document the pessimistic database locking strategy using lockForUpdate() with deadlock retry mechanisms to prevent race conditions during concurrent reservation attempts. Explain the strict reservation lifecycle states (pending → confirmed | expired | cancelled) and why the 'released' state was removed. Detail how the 15-minute TTL-based reservations work with automatic cleanup processes. Include transaction boundaries, rollback scenarios, and recovery procedures for failed operations. Address distributed locking considerations and how the system handles database connectivity issues.","parent_id":"cae4c946-defa-419b-88db-55655e77ad15","order":4,"progress_status":"completed","dependent_files":"Services/ReservationService.php,Models/ResourceReservation.php,database/migrations/2025_01_01_000001_create_ptero_resource_reservations_table.php","gmt_create":"2026-08-14T18:30:08.2209811+10:00","gmt_modified":"2026-08-14T18:42:18.2922061+10:00","raw_data":"WikiEncrypted:/j3nBh2eZGsOhaH4GyKbogm8KrJAx6ZWDJ7Pdb6drKrb9nwpgTDWREvPEyjtIn9xQdXQTv71QtHEseoTwvhrBtrhqhjm8gleqfb/RCV6wO/wy4YN/0z7r5XKxzvwf0wk/t5OFLEJeZyVh7BnjahURQFv+tZkkDez13TXWgbWgHcyz3Ji8O+XcdLZy9NZFGSoz2+hIwikd+sfw6fXMFI3IqOjtTRf20eeIUDhUg7se7i+PL9tdVGZ0tisG71P7VNhxjq5A7DJ0w4dpi0+pTY8zu2lhbJCWQjBxalRlkKEfPTM39FVFw0Qg4by815J9vXUcdNK/DEmR1aPIb3Xe/ztqbjcqdTpDF5tSoW5ysJ/7wf8Dg1hzt52rPANtAJJj4XWbXux3A93cJeb8ERXPcC/p6jmNOyCz5vcYUAJOAdZXaUZCOzpaCvW15PeTWfSbU6wH9WxNQ2WmSn2z75xOfRW5ecz3++LQ/W/JcRNnO9Cju76SL2WYfzsko44RlHFjKNBePMJkzqN/rFV50dFyokUZzLkSjZ7gBdg+NB/QJ/itiiirSZj9iVgOmxND8nwixMUbuDQuRCeRFjIR4M5scGvwzDOFtEgorvcIG7Nmq/PYWNT+cp1293xHTjPwt7cXQMmL9QW7l197Y3YNhFA5L57BHXWcT4fCK7pxyzhH0ug1AfB6ud7H1RaEAOssVmHEHzl41ztgtDkdmy9hqUMVGmKvJ2p26O7TkBcFY7nHXhQFuysZbrmh4aGxQcML5ZpPntb9uM7xsoXwdX28ZBprBC4IFkVjYYKdQOeiD2kwwtAh4BIS79hZ9zeW1VvdgxpPqXGJxT0Rgg0bD7qq59wBwXxMtxr0NUZBPPPFJyIsSVX7nK8l7nbKKishPC80cYLQIs9mtRYo963Jwv80ta8Do6vl0dF7CA3448eLtGxYJKlYKiPseB22x9cAjMU8jrBjT/3mz215pDZyIuEOE7woc5vpYP5araJJc2xTA9dFI+qjmVz01fDetf3mTPFOZzkUSI2mlsKDdP/NuGNkiIJ8fAJqPuhPNi+o9/75GXDkooitWlxmlAEva0HfOeLE1Sfp4ikuIcRknCnJLsQtFCSBYr9vAflXAGSLiP9e1wUvM2R7WlqcUmWgFcACBUp13vcjt33xW4vnzOKOCEuVJ888pEuyi13i+9q5/cmbhPClC2ITdy2pXnY+7VRUmZTCs4o9/X6CGhI8UK6jY9JfInb7UGO2RK3u1BJwkDJZbukWpv3tY8qUBvAFK+KREbwuomERciLvureZnu1WndQ4IlUyBKihm00Isd/zXnlUoSosfz1glNqF9UmNkEsQqQNKJMux6NzkzX5U1kzmXUqIFJFnax9r+Uknh9lpB3rgxTAOn62pGlQiMf/nALo7cw3K+nWlGhbF7bC3ULSYy85iVyg7iD+iQpJRWW3CxQ9zxZ+2h1odHFg/nn9W2PMro0EpXr8OUUifrkg/KaABkw0THHKzlIloFaV4ttReCgtAPR+BsMYjz7P/JaSNkWugYUybtZVXiTw4mkB5xW3JI7nurwKaB+TNDca4p3x0rSUkgcliB58Qsw=","layer_level":1},{"id":"41003932-cd5b-45a8-b46b-cceb2353eb97","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"ConfigOptionSetupService","description":"config-option-setup-service","prompt":"Create detailed documentation for the ConfigOptionSetupService that manages slider configuration setup and validation for dynamic pricing products. Document the process of creating and configuring dynamic slider options, validating configuration constraints, and integrating with Paymenter's pricing engine. Detail methods for setting up slider ranges, minimum/maximum values, step increments, and pricing rules. Explain the relationship between slider configurations and product definitions, validation rules for preventing invalid configurations, and migration procedures for updating existing slider setups. Include examples of common configuration patterns and troubleshooting invalid setups.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":4,"progress_status":"completed","dependent_files":"Services/ConfigOptionSetupService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllCgohKR6YmuldRj/z6qcqjDR2pitBli9Ia+zcNB/epHTLmBoygqBYyX/jJOBhT0WY7vCbpe22qceZkFAqb8DZzKeAHS/7S8eBLoXzPcjtKKyg+k9/VdmoVNuJG75h4ZnEDfMUlm8qe2CMI7OjaRA+kHbQkuLz0EJ94HS40VKrikJzNjEwdwaRPdZNR+WAjkP6PYFnd6nsIshMedwJ1MvKc/XYaUdoplA5bn0MAOXN5ZQVC/AZIC+XLtGejPcX0T4WnLK0kGqgleEdbJJLXL2xANnyrCRoXuDv/n7GAO09reNra1mt5X+R1g8y855x1EHahCGn87FGlb5J42VQBcnhyrThOpSkyf8NI4ZJkFisxq/64QBzfyPSwloJsvfM7rkUy3tZPcid6SxGXEod8Rhj0gSV8H0AioN27rEwI92JBss7JPUriyBtMwxR2z4+jhziQ3mg9OAPvRUDV76xF7JfQa3XqHmg40MSgFs1/ANbT4fOCIs52axVRxjV9x4V44uqDO/vg6RNqty3Zybefw0AQU6cE8lkH2CWrZ7aHEmN19aUBrwXAX7ip9q881tISrLVemtjoY4KjhqVZJJdHGpEaQfitPjN9l9bxg0Q4AMGN9RW4zAeTzWVdFdMoEkaigaVkFzAL3ExafZveH1aNPy9kDsV8M46Ac1oeXPi3TyaujUN/fxRvGR0vKiWRQ4asgZpxQewQrWtFrSWVkMXKQ4pQLO2Foys4HUAmdZ/j7ejA9A7kSx925Kj0uZTyoyLfMAjtW4p9Q3mEauRMS2RRjd6+Zu28xmt52w1xMcivg9JAu8wCqo8LYeNMPzHC9ri+K+xyAiMVLJ4vS190atcXPUV5A5/alS55RBPyY5LZfOL+fSTOEhAT5N3aWKPPKnm1+yc46zNe0iXBIQOKSF/e40mK9BLs2gyZ6aZ7GnA301acBQdL82uGmQOCvB48ViwdnW5bytzHe8ULvKl/jtgrPw/YsuYnMd7UWhUE3vdwyHbhTJ8ZgJpnOW/qwj7eG4nb06aNguWBAuHILENLgU9KjJbAuwWLNGUeU52tZstHayCQxjerq0ltMmz8lnaDW4cceWI491B/mhpe/DlGbBU7H9Mhpk9LBtIcMINMjUROhL9G2GanSCgDD5SgeTheUWtHPFZBAK6t5ju0KZt3taZdLHoo3SvR2X92rvlHAsEgXLQ72/znycR8LguH7BhjnvxNxgoZ+xQcDd2mLT94WFwWLwJ1iCKSmsragp8GgKXRRVhwJUKB5M7NW2jo0ZypJUAvSgVxflLg3Ih336vqO16pl79bnerBvlQpPVPwsE4T3Bkf4LIv7+8UsKeB3hVkd8L05QxdWAStHzegxaA/wInflA8WgMF1E3IC0JRx6BLkbiryDu","layer_level":1},{"id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Supporting Services","description":"supporting-services","prompt":"Create documentation for the supporting services that provide auxiliary functionality to the core reservation system. Document the AuditLogService for comprehensive logging of administrative actions and system events, explaining how it maintains an audit trail for compliance and debugging purposes. Detail the ConfigOptionSetupService responsible for setting up dynamic slider configurations and pricing options within Paymenter's extension framework. Explain the SliderConfigReaderService that reads and interprets slider configuration metadata from Paymenter core, emphasizing that this extension never calculates prices but only reads slider settings. Include examples of how these services integrate with Paymenter's configuration system and contribute to the overall extension functionality. Document their role in the broader architecture and how they support the main business services.","parent_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","order":4,"progress_status":"completed","dependent_files":"Services/AuditLogService.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:37.1512484+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00","raw_data":"WikiEncrypted:3yERI6FkM0skPdXLWnl27OucrSiFcSfyE2MQ2pfXvVCxyIu6PkNXW4P6qJ9roLiRnUTdUXWLkoQ/rO51IySmNsC4rGmKOQee7MrsLshw8n2ff7g2j/CmpGGZ+Tpx/RuH1wCAp3E0vtugl3GnKomWc90GbYO44Mihl/LBnmkOt+vO21VPyrhsnSUq4u3uNHft5d8N2k7wz4ct76or/lPT2AOZrkWx+ZXvD+RA7o8U4Vs+ptP7hDCuW3xsUpvEef2KCC6+qKXQF7y8DBHclTY5O22u2Lz6dBc8bAkWjlMtQvTiX9ZPxStKjajKUByqhDLk87hbAnc7tsujwJronYsBC0fwjLrrTKpRjKCcwOj5LgnCyfivTPuflWLiFcuDGSKRj0HTdIDTW/74uOzEpACAx3Q418aqKNY2TXbS1ieHTMneePN3Hlvpvbvjjzl1puGExk3Xq6BhylLl9KF/ooJcWCyfU4mhjX1SEo/++rX5ZpuaBT/hGGVNdOm/lJtxHOYJ2YGEUMjgFk+A6fXek5fBlxdDjelgW0rCmIRnYPPXdtdDitvuQ9JCbRHF+1QBBmt2ZLkFPm7GLyWeuGNQsLEYTc41lWkS4DXUNzcPPkek5Yn7WBllYpqMNTdkyUQkVMdhDABq9bqrT7BAS7/cEX/drUszYiuUzm9VGhVDufF/tcJ4EzeohDzg54lcTu59D0Ram9+ok3QpLrEWsWHN3rfjJbpyBBt8vT3NXhMyGbV8B7L5oUqI/Cpm9l6gVEbVvPZVL+ksLSFedI4zDf1qHNAbF0ggCGv9mEp2jm6v+7RaC7TAAdZe2Q+qFBlzIuppUCNN2TKn8GEHmZjARhmI6J6BkGoZ6GYloCQ92jADnRM6OAo8OsXdYrmXjmvHB8uu1ufG5hcoppqwVKyhOh1+/diyLjSuavW8xYkGC9Ej6dIFVzBa7aD2j2WVGq3OvJNp5/Iv7MnvYbFYTcekjw7ph65Fssyfmcpzk7PnJoUZEVS3x64Slx8y3sCcny/Uw+odGASPnVFI1gWbvqzkgxvoxvcdtBu1Eps2RbM69Phw4lCYw4/ugykhjAx1Rz5ILLQOYmk9shv03/mttizX9TI6gtt5BzKZn5Rzqfijhih2AFvIYNaluBU1JhhciO80P7q47+Ykm7L1ttiMSv4FxDxTpH1ISqCI8pLH0fXaA/PumQor97+WD+4S6ZvY0tN5wYO2EXrQtcyB8Y/cYuK40/57PJK5aqmEAjo2f+oyGLJ91smBgSiTVygV6wKS5/ZwbQmE28aijwpAGtZj2Avm+vv4kQ5n4OZuUM3f68M8gboQvmvi6p8vDarBwhAZ7/CIb8mfXRGzrlxqwpMEeilCdJmBxzlA8mA4tpt4WzEPQEnqaJC7W5ON4WLNYzU4DPX5i5btB5DEi6gc76zNqQvAJEAl9wa65wVpqZ3+cC6SFDlpGfldLAG67K26Kdp1I7eXzO7WBvPRYa7xUgQd8ZQ2qRLA4jYSaq8jcAZk2kf7D6cIigKMbTS+8aghE337uoetBGICu7fHuKVczszaw/mCEZiI1nwMGcVDWpMgth0E8/Dfufo2Vd5V2h5CJKv6fkK736GlRoFs0komdPB+sCL8kx9PD38QZSVmhWEaDVSK5WM65EezsK5oDflvHpHEDeb1AigP8TNWgYoAUkg9ubkUqLZzlo9d3cYi4uLW84bTIZnPMmVZb50mJhzvjpSYG17PSRg4nppvOwobtMj8bA3FOnKpWzCPjJB4Dhsd4F1HqQ8M21vwlWLnc7mfNpsX62xl2Cija6KLiMefXl1GjCJf3ux+UkobEDj63cy+mxQ4eNaO153Xuv8=","layer_level":2},{"id":"81339392-0da9-49e2-9a37-807e51b40b06","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Event System","description":"event-system","prompt":"Create detailed documentation for the event-driven architecture that integrates with Paymenter's lifecycle events. Document how the extension hooks into cart item creation/deletion events to manage reservation lifecycles, invoice payment events to confirm reservations, and service creation events for audit logging. Explain the custom AlertDeliveryFailed event for handling notification delivery failures. Include event flow diagrams showing the complete checkout process from cart addition to service provisioning. Document event listener registration, error handling patterns, and debugging techniques. Provide examples of extending the event system with custom listeners and handling edge cases in the reservation workflow.","order":5,"progress_status":"completed","dependent_files":"Listeners/CartItemCreatedListener.php,Listeners/CartItemDeletedListener.php,Listeners/InvoicePaidListener.php,Listeners/ServiceCreatedListener.php,Events/AlertDeliveryFailed.php,04-EVENTS.md","gmt_create":"2026-08-14T18:29:54.7050692+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00","raw_data":"WikiEncrypted:W27BoG2tWSBKbrlfVNVQ+jhnraa0wnmgMERgctkchXEn90un+Ggos3Xa9FaBmmyp3rtD6860nxngk8pTcEcpoQDv/cjB8DsSnqtIywxsjYGrVZuTH0RmYLQKl+Zq1oOWL8SH7NxIzcBsSj4exr/sYxdY8zm2zQwTU7TTjdYye46YV/d9Vh0j6rx36/YhGOLH41h3yVCpSOn7I4TCmzZ4b4R62y4H/zLKX3KfRxSYjhg4VrqewdYo3LvA20rf4z37bcCG+5U5FOAQrKXF9b2sMSy/qvncfdCwWMycfim654w5uF/P0UyBcgugKzqoQeSyvr4FmsLG+28/OmueRdapstcWhXGGR9UUh89fWL/dnaxuJ+CUwQC2n99feNwhl3F7WB2bIKefGMeKCa/aPA47MVamjyDERrMhpZmZ8kKmiX5m4GzrkFQ2dOcBWTZUinfOwb/FxtYz35XZCR8RaQSf25wvKWegDqlfVyFN2QcH+LlZdSb/DbdxfQiM2bz/Xb8WTA8NnNtsKcaF+HtS0mWyXnNkbDkZ01gwG3WGHgcK2EZSGFvhvRX+/Taak/BCpLekq9SyKLYLuzKoNUfeCCe4tivPXj0JHVXdD8SgNBChzrmKoNL5/OfncxfG99nL3BPnKrlPPHB0O3Oow3C1ETpm2K6uP7JIbL2K9l9V9NeO87yZem4KnUExG08Tj44K3B0MkcoawOins+vzdItYMK+pqPa5pjSU/jms4OIDGEYhqcbMyCW4kOtnE8DAhs44TplGnuA6J2GPqVSUPLe1XIa6Y538VOVq/asQ0AbvKC6RmhMWlSYs6fH25AM00iDyRqyaP+1TJMid7sTET+GeESiNGv1rvvC+qxnBeHVUOlwIWuqIY5xXeGDjsvKWLV95+rEl1lw1YOpFUujv8aLfaMyw7F9V457URtnsupN6m9/J1J+TSIueVUQs10XbGyNq6FsWdKE9vCnXCLQdA4YsrzdP8oOhQnEb7fZb3fMgkO72v7C0bKqsfeMvmcHC9jNXOzIfwDVV0i1sJxwzVoyQuzyNNKMePlbeOH1DfTjRz2LuD7YhCQoO78Ae3xltlDwL1F/Iq/f+fcG9PF0LzCG62vWKOFBRTAOdk8hyKYAd6H8fOjcT4bwNRtwygTMgptHZ3OI8f4dhnL/hEE50GfcVyV/Y8uVsqH6gpT0E2R3CEGUHgySA5Fhdjlpe6naNOVj8RFy2kxuLWEfh+HI1ChMeEL2gtdck2VFpWhAOH3uUKz6h9nQp/guFRqipWTRf0hFNOVB3dHMDUd1PYb8N3E9OZj960MyoL7y1/x6hYVDjV0S7Kvr7i00v0c9nLb8Hoy6u/EfO8K+cxsttoRzvWObg8BvWBcgSQjoipQ3+cp4poT2Yku3vWSKfwZjjSsWy6vKA1cp9o9Ap+0WHi0pjXAmIbq6WJQ3NWYn3YDGoOm0PbvtcyS7N9f+vvZbQuiATPlfP0uxz7IvZzR7/sNBwBNl8wohDzxP30mwluUuhgDrK9kcsFaJ6hkpforzaRLFQnwVyVOfFoLlaExZ7XGpjRHayNgrnEeFUU+QC0RhBSaNsw0TgKguNXVmXYEmZ4yW55WsWtnRD5OFoJfV9yXUjFvd6iUq9VO85gFKmYL9qbvV9VwPg/zwavtp0dcwbGZD/AXJrlLk9QbWwQOuTUdCVMkrNRljF7Q=="},{"id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"SliderConfigReaderService","description":"slider-config-reader-service","prompt":"Develop comprehensive documentation for the SliderConfigReaderService that reads and interprets dynamic slider metadata from Paymenter core. Document how it extracts slider configuration details including available ranges, pricing rules, and validation constraints from Product::dynamicSliderBasePrice() and ConfigOption::calculateDynamicPriceDelta(). Detail methods for reading slider definitions, validating slider compatibility, and providing slider metadata to frontend components. Explain the separation of concerns where this service only reads configuration while never calculating prices itself. Include examples of slider configuration structures, error handling for missing or invalid configurations, and integration patterns with other services.","parent_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","order":5,"progress_status":"completed","dependent_files":"Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:30:10.9305503+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00","raw_data":"WikiEncrypted:xIW6FSR5xsHzmFFuzwoOfnjq7ggwBk47TYV8NODkwSD5VUde+q085xdz5IHplkJ1wGfTrHtsRRIcmLHiwbA2l0wQHAhqaYEO+Js8A8WTNXSSIfE15pbJHQG1uwZ09i2JqwvhKAFn1flHhyAQbqlucGEru4mt4bB7N/gbOcBq1cjZNtjFX8oRrfmxaWauHWFbjNQPQkHNTMcdGGxnmBVzdD1iQ8dX9aFe3fB+J0J8l9yaMTNCLGLr8Y1uq2Nt9xR0nSptub4R4Nygs7gps32pA5kkUAvpvm64y/KyIxAT2wbUJ/010exam6lhuU8pHvPWjpFHTzzIqsneaiMM6TEfaoV/5FnIPaRwjjbWT8XMGIQbhO9v6SvK1cfG89EoF+s1ham2GsEaQ7GG8uOUQxjtm7SRS6yG2wDxlqOV63ENChPB6Y1HcFgMwYR0vfIKJneIJZ7rGFGWCt2iv0mxg3+pp/ajPV3VNV2mohEVuLQSdhgwOLfnpDd916hD1gIz+5BZEubYPOIUXtwVBonVEpr2dvf7PTP66xVyopM/k1EGfsW+9x1G2jnLglNm1840ofTX7IpC+0VCo1/3SqI1fMHeRUrv5WRaJSh7M8YlF26V+81/Zc1jur8ewIunPbJ3J7p4a3bw4p85qcKRyRekmf03GFcLFscqMFsmPItwCdC2jdcyF1PGl4mJVEM9GCwI90FApFXll5BmATVk8RFZaTnvB9PIEiSud1Gfa8zZRNHwrwZLgHkTlB/JKfa6kw2MnsbK/7Ej+b8DZNeOHL+F8g/NmJ6U17VWOh4vfuxII07sdZeqiGgMrYVAccUvabGeQP3R48ny3Z471Xpg7FwUW4mL9zDpFO5iwZen9KEByxSBNMcucP4EZ9d2x8xOsw97ycq005anwzzkUe241dm7IyPZIx6Clo8B8YSFvZ5/7Cb7PW1juIvcBk0rGkF4qbZBEoMcEqolQJm5sTVcQfTSCJETyKtOmhx/rUke5QpftClEPkG5/VJz6jS5LSC/ZZZYeS0xbvp38A2X/lChuuC2eKKocsJWTdkBumxRpA2DKW7ck5I3T5Ib2v6petQC11VwkuTfsZbpl0RQWcUxwLlKHfPSzDV1IWbVhhNmrENi6M2NRkDaVHXRXgkquj107dvfnfrb1W6sLW1x9tBPMYrPdt4ui6LVJcKyKl33ObCPwOzIxKZBcKUVKQcI6hfJxTefia4es5ffiuXD2mPKYgLEbFGdVzC5dXzXtTKlY9W8NelWNc0QXTWpCCbZYJDf9MqfGFU/gsROpPacOi3e/VnUCiigA0RLjBotjWqX0dMKATZcA+TD2tdKRXV4L2/cKrICfYz6JccAS/A63FY6WeDrfKCj9eQ0K3FP7ooz9revgK7AJn1tgoKXwBx0+dJcsgle5Xr044UXLHNmtuAesm9Nr1wG+2009mgoMmhiJ4m1pCXH1S9hcLgKCBdSVFPGdCKRTZzjXR6gwJ7J9ZHUixDenn/Jhg==","layer_level":1},{"id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Admin Interface","description":"admin-interface","prompt":"Create comprehensive documentation for the Filament 4-based administrative interface. Document the dashboard page providing system health overview and capacity metrics, node monitoring interface for real-time utilization tracking, setup wizard for initial configuration, and audit log viewer for administrative action tracking. Detail the reservation management resource for manual intervention and alert configuration CRUD operations. Include screenshots, user workflows, and permission requirements. Document customization options, styling approaches, and integration with the underlying services. Provide guidance for administrators on monitoring system health, managing reservations, and configuring alerts effectively.","order":6,"progress_status":"completed","dependent_files":"Admin/Pages/Dashboard.php,Admin/Pages/NodeMonitoring.php,Admin/Pages/SetupWizard.php,Admin/Pages/AuditLogPage.php,Admin/Resources/ReservationResource.php,Admin/Resources/AlertConfigResource.php,resources/views/admin/dashboard.blade.php,resources/views/admin/node-monitoring.blade.php,resources/views/admin/setup-wizard.blade.php,resources/views/admin/audit-log.blade.php,05-ADMIN-UI.md","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00","raw_data":"WikiEncrypted:WWG9qBb74s3FuYyeVUFZFNVBgoDDfQnTVf6JIXSs+2ZVT/jBd0Tohjq15y1NP/7b7yfay4ZSf1dP5XPBIgZ2qIOZlf+nL+6M8tb6HXSMy25DW9Y0QpDfjGLj5svH2X2FhVYOyXBXnPysCjr21fJlupXgUhxRSUkrS+zYSjJRhIUzGudxMrNMSZ8NF0DbUpK0CahdE0zM0i8bwhkb9tNp6SXjrVAuZq5MsPnAjF+sSV6i2GhSWNvVO5PdzwyxrQxKm8JNXSB4i/FEmKbv0OXYYvggSumGhaH8cuBmRYLfthNh5Gi+pXuyEUcmKhPO88plbMlbqWYqwYt2ugQQGzWrXu2rmkXj4P0Fl+EHJrW1ltv3/ZQgkXj2WDD0ZQ+sXCp+3u+kKK+wLryZgRTURTY1IYz0IxZVZbZ9u5SP3DIkznH+KCpE1CDSFPK9UczM3mKLIAFRIDeF3Zx2BlIJH4wriMamYO1+X2XiII9WEOmGM6O8Yq+qU8b3BSU8S2Yty62QmZJup1yPi76+r1chYOQJY6KkCg2eYx0THGFdg/Mp3cZGk9GIvLYqdoKR4g6Id8vp1TG2SFyCDRBqT02T6o9akze6PQkxGnSx/GpPAgNV0SY/GCE3o48E9Zrpb5eGparA8D7mLpFoFNsOIxvRICKg/I31crOo/t79SM9Kq1ZGXc5CYlE/XkLIc5UyRld9uDD743phDhrmdozPoS07ykjParVA5qn+ZOoV+jLDAM5H+ZNdhClTSqsAbdVZdGhLBD6+k6j8O4EHg4D7TNmpSyNTc+oaugSuR6BNWR6hic53wSggxsegofanP9LksIpjyJU+e5I2iDUYp+ki0kgiuTf+T1Pnku1+g0OgeKhyr55iulqHVPKbUuUMZ+rxeR+Z9+GkaqgrahoDQ/BPNS+i/QMvqA38np1uMgCBuxFf4YbDIQlIVFhq6rEYIqYSbeSWsArxowMXCpYsHsm5zRmEumjbYf+ggggtn67AoKX6h6goXCUzdANRWXD4cISkSCM96wodNJRY6v/+Gpl7rMIZTM1YMnzj69inbN+ip0VrcA7vX6c2OnkqgU/CVIqJX2rZKfpxznsfVhnOKstzhmB9BDqw0l5E4lM/rLwivfGJCdAX0OqMIZV9sfX0X+eQw0jizyByPKGcpSX1cfFIXlkC6yAOGvRMN0HY4Yp9d4eNBKG8TVXBYVjm8Lt9qUGe9zT8AyD4en+J2B+7NtrJC0T9nHqJSwTsWa2PxjjjhBDk0m1a9bBuqpRWaoMuwQW6XySKdlwPsu/pNJoIToaBAqjQUw6WPMwUN+OcLS09QPOmVuzobrYDCupbXc6KdBNKpTCvfEzURi45lydJ4NtzDYWruk2RVyzLqy39ikPt6zyADdD5sPK1iwwHX8blhV/YTogPk9AucnCuCnYdtam/n6wDGS9uI4JzI6gaEmZkud/5z1B5+uKULCJVcgTvEVEv/h9rENvVfV21KwYUlia+bBB001uI2eTCJT6j5D8Mjy7PpDgiAWNpbxFI0xMTC4HYbcyR74T0gg6JUs4Bts2ePLHso7wPmu+gof31B00VK/rU9wF/A1Zfp1Rj7xXjnnIu9RBFSnNhETP9smIcQELmT41VJ/VFVI+yH00oam7mqqpxpHyftBUpRCXRI6NgUjhvUoC9sinE8/t5P2q8mwenT5elBMdoDfC0iuXontweV6MKxV6rTO9iRAsQYBNbcySA6Ha2dQcw78wiINdkbN/K3qRBJ+li6rDsB57bgxrAn2R/frqUKqP6V17ii0YJjt4lM8AZBCA0/dK1MiMqAb3+6Z80/+rDHlAmuYFVYrdRjc1Mor5K/nsJ/dxdcwlDyFjpEEzhHC0g6uZU2GF33sELr98rp2BMSD9ruh9wGk4wJCkdCrT++AxE+81fUhrr4Ok7XC1IGxshgsAjGikGa8PyPpciEkBRbr/Y+OOpbMzfdibXDpotTn4="},{"id":"268e6157-30a8-4047-8abc-f7116c8c4969","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Configuration","description":"configuration","prompt":"Create detailed configuration documentation for the Dynamic Pterodactyl extension. Document all configuration options including Pterodactyl panel URL and API key setup, reservation TTL settings, and alert threshold configurations. Explain how to configure dynamic slider options for products, set up pricing rules through Paymenter's native pricing engine, and configure location-based restrictions. Include environment variable configurations, file-based settings, and runtime configuration changes. Provide examples of common configuration scenarios, validation rules, and default values. Document configuration inheritance, override mechanisms, and troubleshooting configuration issues.","order":7,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,Services/ConfigOptionSetupService.php,Services/SliderConfigReaderService.php","gmt_create":"2026-08-14T18:29:54.7092437+10:00","gmt_modified":"2026-08-14T18:34:12.6344536+10:00","raw_data":"WikiEncrypted:aC5ZtUyEKPSxjzg//aVllB9TGvdYeEh4zcG1OGQGWJSFpFw8F31SqwuVj2Tmc7rXwB8dEu96VYbSi1y6wDE7kKK2UgLR4P2K9gN0159Y9k3pDIXhYYPbGcpM4naLOh2ct9kF4sM+qqf9x6UeOT4BXyRnmTrJKxiq5Oc0E0QAeYHOoMvOrwO40HJJuBoE5oj4FKQmaKjVGTBJ02sjiyWWijjRp6Z4X68W7x2fZWXKRMqamrO0Jb4JSNSwadPRgpuG4M69s0C8uO/wcWkW3mc8XYJ3GGJm2tsy3nufzuKj/JpeKjcOFBNXy+5oAzRsfGbE/7ThpW/YS/wGQt999n552y7MqYi4ch+5ev+eiToriOPEa3ktdzdJuhaQITVT9H4ecRE8lU2dkwCb0h7noqVxCvVMCcEnQFeYm8yxrfuATZBVDVoY+WVt40LAOO7yhEY8GM1rx8Yk4z1Q5vgBajLub0MzD+ymhq9dP+2ViV7h1Krrb8iNzJhxG/VGJFpPo52M2iOBhDpYxjsOT96LJRwaa0ZW7puYfTpQc97upTEJ4Q+1RWjWRZ3b/6MTS1Wjo75IwvjMZfcrSIy1mhYEQ7ltbl2wEN7yjcZyNvkvpbBaQOx4mnmd1/B7315gY6oXkNkoGnu9wcLO6yaIGxBrxUYXVYtIxTx5+vZZZ7Zkfgo4FU31S400AZz6SLpH1hXCpxoh+84FR1AGRxzbtuF/D9Hz5T6CbjtzUvogCtZwtK8KKyKRQiJeqB7zLhgZbPOdPlVdzxPjCkzwalo6eJi7z1BeKP+2PLviiCtLjm0Vg3bPuFTxAudbE7o38IPWFk/KUrCOXRZmDRQ0QxoHdHKD57WP+ztwxEHTRIbhuQlLHD9PwHctTzmbB8k09gIgUbPiCremANpNY4z3IcfRNwfkQrXl7ydGzB8/b4DPobAis2MzObceYaV4K1CSe8Z4vi54MQoB94ZSOzfhI9W1Txyd4OAC/fiYpvC2PAR5DClCudsUMf78QSSz9KWqdNx5IA5Fw6+Ue7ike7NdYD4qjdhOhQC18xtlNBbNAbMFfCa5Jp306D75tnS+BYGOUixzCVtc6AxNw9LyEdG7FgJYu5Xv25V1sF64x7MQsIJ0T3v30Cn/O3V8CTg2C8J57u2yiNhgJnQbZu449Vx7hQGpC7v5EJ7TY8R5LVa9nSmeza3oU+ojx0AQ5n0iMTHx8k779ZVqyDSHeB1flPO8DvRrjfU/8J6h8LYIMNhlkzo9Pu0TyLBVBTaIPAYGUEVdteObXzPA7RbRfqU2LTXwHO6dL2pbEbwSB4RDvbQmEVSXPevg66O1IqLdaTxDldIRxWYkMwYLTfbziREIB8iawpi15Re5NbEu2MsbUvDLHXlAwRRN6mzzxmy05Kt8x7AsUODeK/MfLyjKyNU2cU7kUarJTH8dTNjPjsDWvGH8kFHod0HS1LDdQiFZgS9zGuAiqhlAJyBIhW+//2gqdCEwRD+zSXGJkiH22CB6ZNmI5+ehkDF3eS7wMQw="},{"id":"38e0cc55-da9f-4918-a1f2-75915446628c","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Testing","description":"testing","prompt":"Create comprehensive testing documentation for the Dynamic Pterodactyl extension. Explain the test isolation strategy using array cache/session/queue and sync queue configuration. Document unit tests for service layer components, model tests for data validation and business logic, and feature tests for API endpoints and integration scenarios. Include guidance on writing new tests, mocking external dependencies like Pterodactyl API, and running the test suite. Document test database setup, fixture management, and assertion patterns. Provide examples of testing reservation workflows, availability calculations, and alert systems. Include debugging techniques for failing tests and performance profiling approaches.","order":8,"progress_status":"completed","dependent_files":"tests/Unit/,tests/Feature/,phpunit.xml,tests/bootstrap.php,tests/LaravelTestCase.php,tests/TestCase.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:34:38.6234582+10:00","raw_data":"WikiEncrypted:a51tw9+B5Xez88YuZqi4cJe9KawViinxS2+7PJ4zWF1rrTftkwDEls6S2T0QV1ucEPoUFZro9LJO7G9GwE72MTGAtfPLOdeumQS14HNLDQG+5w4Yj0EjNpVhDD/LYTb2Z+TFs2fph6r9HcoGga5J5CJENUVHHME+3w4T3sY7r1LbxmdyPyW/xEAihsXE2dpetej7CLbeC1ZFh+U3gV4SvltqWUgNnGpayo+DBxvn77MG3ES/O4YJdySlj+1Os12BTtIxH1K6BgefwkkLYKVhgq1qNaxEeeA8f4iCvWUELrEHKYhNqLjLD1FVVjFIVA1zPA/OJtr1otj3VY4RIP1r1D1jkZXHfh2lOleGajqCZ2+CmLnzYZ8F6aM73iAGAKdhShDFP5/32OMgERPFerb74wjZkBxgatUeyeMqAZM6OuHF2EtFkIJS2+JxkR+BRW7kMUxi1/cZDsWt9L6euxUocDZ5e796Z2VrjzNuJway3Taxlx7h9OOQ7J3WN24bd9go3mjqH9etx6tpAvVqZfTrasdIghz0BbxZwLlxEEWUsyBQzCgUaMf+8gP05aQouS9KkMU3v1xI+yDyU1xJ71eYALrPbEb3pV/OTNOdtiB0JWJ9L0KE0/n4a0aimCjQgzhe6e57MNf/iXmxt7QylkXutJICSzp0RmhRGKcOMCE9FqawGQOzO5L7BxVssk5XAWPcBl3iUp/hgsyFIisTTa5LpuCkkTLwl02IeQ1bAl6BZtytVfjSR6f6699Tss64OOxmcOiBBP6v6z9P8oPdn/dMnixDxMvd9kqoMKu57ICbmrXyElUSpM8v8Sbft0whvl6N2iHJuA7k1oB3MdSiryLFiZcLnN3OXOm/7zKjJlJwZjLKAPqWwszjuUarPKQIURllo6WDAswpfY5YGYqGaAKL7BRf87paYF14rlJAVIqYm0jFEYkDz6YUnX8Z2fQW/BCG3QJCKgwKOOr46mK0jytSonHY5QcfES9Nss0JdrE1/mWiKF6pNUWEWhBsHUVHJ3QKuxeJRARxJxalnGP+Gv74TvrIQB1wha0lCEDmn/AbZTSEGVDPxxuI1D1QAjQn7CN1NSFpsCyjmsizENXXfK3iKBeG+qUsDV8VdS36SFapxDf49uBOe1dCQm14xLuA1x+2y5AwvWVXGXKEv+1RMjoJerAe/Uuzw6UffOY/6O9M7CaRczAqdnvxopqj9X8k0Jq877ULSWgOfvMdVH7nif00lIV9ZR9ZCkMvKPepX90mlbWxcbDjnRKCQ6HhOHzRlQbQSGGvU8DoFpCxbpMuh5iSBV8RVz+O8Rrm1eiv+qd6QCk8g/GPct4MgI5HgFa41lM6qkCBQ0wHflr4c7vxJIEPye91CASnHMUaa6HTvOw+qVJ/4HMHATad7rP4wIXFR8cbYFWOIPqUEfo30zCwD1OsqNQfVEbhoEnoGXfqtKhUZAO5TcmNwC7r1g0BdV4QbONnwrC5sRDHhpeHKtgFv6/+6RDlo6demcQ2byICHPqcp4zBDOrUkzeYgDb+ceBG0ZcP"},{"id":"b4342e47-a056-4254-9690-dc5da63d95a5","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Deployment","description":"deployment","prompt":"Create deployment documentation for production environments. Cover installation procedures within Paymenter extensions directory, database migration execution, and environment configuration requirements. Document scaling considerations for high-volume deployments, monitoring setup for API rate limits and database performance, and backup strategies for reservation and audit data. Include troubleshooting guides for common deployment issues, performance optimization tips, and maintenance procedures. Document upgrade paths, version compatibility matrices, and rollback procedures. Provide checklists for production readiness including security hardening, logging configuration, and alert setup.","order":9,"progress_status":"completed","dependent_files":"DynamicPterodactyl.php,database/migrations/","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:35:51.3476266+10:00","raw_data":"WikiEncrypted:0IKfLNOWe9mZfG1jVts3w0KU7kGval8hY4joZr7NlOcelXJ6LZUytJe6IZ8coCeFm9zKznvGyDJ7LwZPGHo0EjzEqz6/3zcywNYNJLGSlRWTPPq87v1g2PkP1EIClkfcI63o4J/bue5dLpbCh2NAqpEuqwr3B4TY7c+NHgmFdFKx8p5wTsybENJtwmxt+vg+sE13RDqTrKj3Ep2nzJOxC4FDSSUzN8xW85LvIA7TDKBGpas/5mjljfPAzLq6r0WZRKO/c7TNSph3WOafiu4mx/skAbSsao2qXXnjtdZBmH8eJ9JrBzNJRy8nbXuWMhWWl48Q2wwnuT2poCyzR1Dg6WgndAhAO0lBYBboukRMX/oolcYmYmyz0/7ruwYvTvFm9ZO1s+z7u8jFMd0FAU3VG8awgD6x1wTbsFID9g6Ajrvpw+WuFV1szydlDgJoFUmxj7oJqUbX4W2gdn+fhGfTzH8HANr2Nwdblt1Mz0fVt5MgAT/fSZc8F7YLk2tZdsjVCP0rSc5O7W9wLPDNXrPwcDXeamUPVOLajY6iQ7oEzbee+25uamYUXUfUX3TAyDcO51rhBG4Ftp1KOoIrd2kqn+QvwAC9ncHJ9c7XPEIEnSvsEsum/aCxzq5xnxerVeHc9kCgPhC5IEN+4gqlrHsq66QBxTe23e/7gbH7iekc+R+1ZtDKyZKBaFCXT3sE38LglG3lXqNT5Z/T8L0X7Eh4tWhyMY5ahHGiRiH+f7v1JVZkRYIk731WBuD3vYycgrCEzufUAG4X8h6MD/j81KNAQgqBgZhepeaBZ5wOsUo//6ALtkrc8nd4IArLy4DCQ91Uv0g8i1rLP7uGMzQWdFXuVkoa4mQ3Uv4YccHv6euJ+PqB8oM85zBRp1UJzr5isxMOttbYNggJFzqAj5GGETiblr78n4nMFmcoTTlimkw1zxxE19DTDa+Dg+iS1vyPeHB/aVwVjDJMKk03MpPyU4TA3pmHF1Ycn6bMLsb4SeEgUl4AUaIrcfs/oxOVUPjODxJXwXhs7EIQeRGe17NnAd9nxIqfl0T55ToCEAwjP2Nrpw6PyFnxFHH3uhoRbqbsezdeAbIHOOGapEaAlR4CP9GBnBQ0nS97uB2UG1ud2B1hWwrKIMMnUMDVoIEXu4qjcFKmpSZCRudkqcO6T4hbIYXONNnNzVWp8FWJJrNI6dJyhEUION/PH9GDSxHbtyzxHPuqT3NJeqeAE1bedpi4PUvPBHRk7p5XIrodzlHuojBM6PgJr1J5s4AKCjMX1jVHcbxlVNDq4cAxNvKSmmhBLKIaalGfkpczkyXL755JxrAWnSv/RmsPQy3xpgJNCcVJwfT4GsPuDmyEN1Gr062Y8XWFnt0ErqUp6pohdqjcRP955K0="},{"id":"d7805c08-5769-42f3-baf3-7d26d02b0309","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"Troubleshooting","description":"troubleshooting","prompt":"Create comprehensive troubleshooting documentation for common issues and their solutions. Document problems with Pterodactyl API connectivity, authentication failures, and rate limiting responses. Include debugging guides for reservation conflicts, database locking deadlocks, and timeout issues. Provide diagnostic commands, log analysis techniques, and performance profiling approaches. Document known limitations, workarounds for edge cases, and escalation procedures for critical issues. Include FAQ sections addressing frequent questions about availability discrepancies, reservation expiration behavior, and alert configuration problems. Provide step-by-step resolution guides for each identified issue category.","order":10,"progress_status":"completed","dependent_files":"Services/ResourceCalculationService.php,Services/ReservationService.php,Services/AlertService.php,Models/AuditLog.php","gmt_create":"2026-08-14T18:29:54.7097527+10:00","gmt_modified":"2026-08-14T18:36:13.4250001+10:00","raw_data":"WikiEncrypted:CaKOW8OSSWs4aEYk06Hu0hGGy7zXJE5t3XZJK+9x87U7MbBuSJQZj5VKy37lfAZW3q2vRlHn50goW+5RwQbDeoMhFpFZEEzDL5gCwCaITqqH/4PA5QAC8SQsK/m9Stg8CVfgSwRPcjqeDdnoDypBh1fdMvLZF0RYierFYZDwPeH2eMVmCKB4YBkznINpKg6pp0bhtP7QFAud4i5eI0mrWTnnmQM0/Fm8D/URDk2jxiu8HZrJijSeYp/9pRUbdT94xkQJt8lGsPFE8IOfqkvxBlhDvWMDe1EVYm0bVSA0tN7xWAIPREED3slkF3NxFzG1NTXW9zSr6uUMqSGt08YWnaf/7n2BZPcTAG18DUrn5u+nqPa5vFvmMy/k6ytnMDVEJLhcMuL+XeIIpEeQ7ad/8/smz8tXqgOFLdRsTQzBjYpeeuiX3uaxX9b63cDwSpukMekATk1QYaBENPYVfSlvyCBVES4Y7MnQtOnEiTzkQoEVIujF4YP1DVy5ICDSOqmr5LqFvlN0vIryrzyz0GT36ID6QO0qlmx8d33pTOo9OQ1l1Bzk4PtDkRJOLTfTX17NHEcZb3mdq5/I2IcGZXb0pXbBfMiTNqT2aWiNekFYLUgIMJoi+2CFR5qpZk0sNm3zcTEqO9sw4NprNvQNguhzy98n5yjPqYfvddIwsEa1O3MRlTDY2L+62G18vVm8h+0OPer1e+3A9eAom5Z/JlDr3C63JN0NjbN89/wZQTGfnRCUxM1cElIir+YYRT9IWeoirPRiopMlnVN3FbifarTQq24TD1OiKZhJI46I3h2wCbgYbDHrMNKR/mafngJUOiDVrmXPtXVPqesn0gc2dwIlzWlsCiRRV80CyHNJ8+w39zR12sPT9uZ4AWuwJpCR9zG8VywlyjfRaswQklwJ4vKLDFA0f+AK9BywEGxTXAeEu8aX3BDkZb1aZYfFSKVR/aAUdGGfcNPANPR7uQIismqhLqb3k6XrUJYFVl9/KAOa1P7vyTICi9RzuhoT8v6BmVxIPrvkXR4R2Q8prWTJXsplBYcysZQ5zSyP9Ryq5waFYjJ6N8lJF21pi+qT0JnbTvWnSev3RXONIRDgpRI1Ij82UXEQbil79Fwdn9PXyRUMaxX7JTCBUuZPCQuQuI2bgoHTLelipVQopSszl2+tijWULGG5mnMO6ZPFI9kVrjfYbO3RSJcftTevqvzT5vQh+J3A4iPS2BZHMAQDxcFESeeRCeePgTebTmEjKFiwfeTdo6CJtPt80xcD7kCeD7nqVT6YUyzPUTnMYSFR+H7lwbt3fxfSmMn/7hUuf8GuwmfXWaOnNUhyk1QPsebyzm+ope/uTmTo1uSScPcVCnLFS2niKLuCY36cklv2V5hlvv/UAHvOLZFKqd/XSq8rJRIsFQJVz1FgL12PbymZcgcEOGh3e1vbdBs/oObQhh1D0juCgwcjR/LE6fthIY3mMUyehrrBpM+Q7KLl126EKSLPUHbr8aQQ77k5H7ysWpUdrXCvkjUgUFtB/zIJ522tyIv/zBWo"}],"wiki_items":[{"catalog_id":"b187b195-6ed5-46b6-b51f-7908cd7a817a","title":"Getting Started","description":"getting-started","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"cb817d16-6d74-4b19-862f-7f35d8fbe2f7","gmt_create":"2026-08-14T18:31:48.3101788+10:00","gmt_modified":"2026-08-14T18:31:48.3153438+10:00"},{"catalog_id":"b37e64ce-adc2-46b9-8313-fb2e0630ccf6","title":"Core Services","description":"core-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"24a7e201-6cbf-483a-aa9d-07769f8ab369","gmt_create":"2026-08-14T18:31:48.7603804+10:00","gmt_modified":"2026-08-14T18:31:48.7650642+10:00"},{"catalog_id":"cae4c946-defa-419b-88db-55655e77ad15","title":"Architecture Overview","description":"architecture-overview","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"752bcc4b-21c9-48f2-9375-e4a7d290edbf","gmt_create":"2026-08-14T18:32:00.8097338+10:00","gmt_modified":"2026-08-14T18:32:00.8191346+10:00"},{"catalog_id":"eb6a03a2-b42b-4ba3-9260-ca99600a7ba1","title":"API Reference","description":"api-reference","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"188acf53-87c9-4598-b284-fc851204c59f","gmt_create":"2026-08-14T18:33:07.2502892+10:00","gmt_modified":"2026-08-14T18:33:07.2561025+10:00"},{"catalog_id":"81339392-0da9-49e2-9a37-807e51b40b06","title":"Event System","description":"event-system","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4e131740-4a2e-4e72-8579-cac21302f79f","gmt_create":"2026-08-14T18:33:07.7183655+10:00","gmt_modified":"2026-08-14T18:33:07.7268419+10:00"},{"catalog_id":"48f92aa5-8812-4b8d-86e7-4a57b5265eed","title":"Database Schema","description":"database-schema","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"18e54911-5366-49c0-8103-29d10e4e011f","gmt_create":"2026-08-14T18:33:14.4799917+10:00","gmt_modified":"2026-08-14T18:33:14.4875222+10:00"},{"catalog_id":"268e6157-30a8-4047-8abc-f7116c8c4969","title":"Configuration","description":"configuration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2f8efed0-50ff-4219-890b-30cafedcb7bb","gmt_create":"2026-08-14T18:34:12.6286194+10:00","gmt_modified":"2026-08-14T18:34:12.6349718+10:00"},{"catalog_id":"70c4a2bf-ad15-40c9-9444-cf940febe76a","title":"Admin Interface","description":"admin-interface","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ddc45e78-a548-4483-8c73-8d225fb09de0","gmt_create":"2026-08-14T18:34:38.2805369+10:00","gmt_modified":"2026-08-14T18:34:38.293766+10:00"},{"catalog_id":"38e0cc55-da9f-4918-a1f2-75915446628c","title":"Testing","description":"testing","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"86ac6693-61e7-4765-aec0-21a789d6f26e","gmt_create":"2026-08-14T18:34:38.6054896+10:00","gmt_modified":"2026-08-14T18:46:24.6647446+10:00"},{"catalog_id":"b4342e47-a056-4254-9690-dc5da63d95a5","title":"Deployment","description":"deployment","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"16154bc2-4252-47b6-a053-e966c87c4343","gmt_create":"2026-08-14T18:35:51.3422689+10:00","gmt_modified":"2026-08-14T18:35:51.3481463+10:00"},{"catalog_id":"747fc3af-47c3-4d1c-9afe-b9b2ddbc6e99","title":"Public API Endpoints","description":"public-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9573fec1-f465-4fe6-8c91-0bb4bba9d247","gmt_create":"2026-08-14T18:35:51.7774049+10:00","gmt_modified":"2026-08-14T18:35:51.7838723+10:00"},{"catalog_id":"d7805c08-5769-42f3-baf3-7d26d02b0309","title":"Troubleshooting","description":"troubleshooting","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"382a8981-d857-41cc-ba76-b0604b2c2b41","gmt_create":"2026-08-14T18:36:13.4174124+10:00","gmt_modified":"2026-08-14T18:36:13.4255738+10:00"},{"catalog_id":"3fa530c8-657f-45e1-bfb4-39afe8443e9f","title":"ResourceCalculationService","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c673875c-4422-476d-ab2d-b9a260baa620","gmt_create":"2026-08-14T18:37:08.3998082+10:00","gmt_modified":"2026-08-14T18:37:08.4061304+10:00"},{"catalog_id":"e3386639-745b-4c62-9148-1ee933d1e0b6","title":"Companion Extension Pattern","description":"companion-extension-pattern","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"210fa0aa-e1aa-448c-bfce-fbf72a83ecea","gmt_create":"2026-08-14T18:37:13.2534237+10:00","gmt_modified":"2026-08-14T18:37:13.2587676+10:00"},{"catalog_id":"366e7e10-0359-4523-8ce2-a28bf6870f63","title":"Resource Reservations Table","description":"resource-reservations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0ca0beb3-87ec-4453-af30-6fbd3e60b82d","gmt_create":"2026-08-14T18:37:33.4246073+10:00","gmt_modified":"2026-08-14T18:37:33.4309965+10:00"},{"catalog_id":"f36492de-4fea-4b83-8237-0f42aaca10bd","title":"Admin API Endpoints","description":"admin-api","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f70303b7-4f5e-4d4c-a3cd-920ef1064fd7","gmt_create":"2026-08-14T18:38:16.0146152+10:00","gmt_modified":"2026-08-14T18:38:16.0214739+10:00"},{"catalog_id":"2babb181-df9a-4da5-b222-f75f0ec91241","title":"Event-Driven Architecture","description":"event-driven-architecture","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6037ff6d-e047-45ad-a568-3493aa4a5351","gmt_create":"2026-08-14T18:38:24.0139017+10:00","gmt_modified":"2026-08-14T18:38:24.0201114+10:00"},{"catalog_id":"f090ff65-6cf6-4648-8dce-03419ae86c77","title":"NodeSelectionService","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2970fe7b-6d2f-497f-9362-3e73a595927f","gmt_create":"2026-08-14T18:38:31.2002859+10:00","gmt_modified":"2026-08-14T18:38:31.2045805+10:00"},{"catalog_id":"2a7c8252-2ad4-4ae0-a99a-39d48b4f2218","title":"Audit Logs Table","description":"audit-logs","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"8ad6f733-a3db-49b6-a00c-339663ececfb","gmt_create":"2026-08-14T18:39:21.8099259+10:00","gmt_modified":"2026-08-14T18:39:21.8195394+10:00"},{"catalog_id":"23e784fc-87fe-4042-aea4-f06d5fbddd59","title":"Service Layer Design","description":"service-layer-design","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3c632a4e-8679-49dc-82c7-17ae7c52c2d8","gmt_create":"2026-08-14T18:39:30.3683013+10:00","gmt_modified":"2026-08-14T18:39:30.3769574+10:00"},{"catalog_id":"b7bf7508-7549-477c-aa0b-c0ccaf33f95d","title":"ReservationService","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"3f58949e-c164-4ba4-8839-a5db0e9d04a4","gmt_create":"2026-08-14T18:39:48.115098+10:00","gmt_modified":"2026-08-14T18:39:48.1240262+10:00"},{"catalog_id":"7fb2ab09-a1bb-486a-b39e-9cff1a180980","title":"Alert Configurations Table","description":"alert-configurations","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c0fb3667-0a53-468a-bf69-5b8c23b9764b","gmt_create":"2026-08-14T18:40:33.2193788+10:00","gmt_modified":"2026-08-14T18:40:33.227889+10:00"},{"catalog_id":"8e2180ce-6afc-4199-856d-14944750075c","title":"Real-Time Integration Strategy","description":"real-time-integration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0e6b8371-2ac1-4df0-a22b-347f3d0d8af8","gmt_create":"2026-08-14T18:40:38.6121131+10:00","gmt_modified":"2026-08-14T18:40:38.6195007+10:00"},{"catalog_id":"46b9fc6e-218d-4212-a930-0fc7713261c8","title":"AlertService","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"9f7b7836-6cee-42ec-8b13-c25eea79ab76","gmt_create":"2026-08-14T18:41:26.6797165+10:00","gmt_modified":"2026-08-14T18:41:26.6873261+10:00"},{"catalog_id":"db81e08e-4803-4640-b5e0-202e80fb914b","title":"Model Relationships and Eloquent Models","description":"model-relationships","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"6b790301-e99f-4c01-abc6-c1d2251b04da","gmt_create":"2026-08-14T18:41:52.6755452+10:00","gmt_modified":"2026-08-14T18:41:52.6850373+10:00"},{"catalog_id":"f3550273-5462-4317-b2c2-6354a1b8c98d","title":"Data Consistency Model","description":"data-consistency-model","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"397c6189-f7af-4992-b081-938fbeb2a16a","gmt_create":"2026-08-14T18:42:18.2848019+10:00","gmt_modified":"2026-08-14T18:42:18.292848+10:00"},{"catalog_id":"999dcde4-2ab7-43a2-862f-b76e65b760a3","title":"SliderConfigReaderService","description":"slider-config-reader-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52e74833-e71c-416c-abef-6a52d5e7d237","gmt_create":"2026-08-14T18:43:02.8864404+10:00","gmt_modified":"2026-08-14T18:43:02.8944335+10:00"},{"catalog_id":"41003932-cd5b-45a8-b46b-cceb2353eb97","title":"ConfigOptionSetupService","description":"config-option-setup-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"05d603ca-5277-40cd-8db1-42b50d13a2d5","gmt_create":"2026-08-14T18:43:06.0109013+10:00","gmt_modified":"2026-08-14T18:43:06.0180514+10:00"},{"catalog_id":"52295bf9-bad3-435f-beac-e59e3eb28421","title":"Availability Endpoints","description":"availability-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"4cc16489-70c5-4fc7-a82a-79f9f722f7b9","gmt_create":"2026-08-14T18:43:09.3656506+10:00","gmt_modified":"2026-08-14T19:47:29.1142518+10:00"},{"catalog_id":"055b0b2b-5a30-4340-8b5b-46fdad73194e","title":"Capacity Monitoring Endpoints","description":"capacity-monitoring","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e1b71f1f-22cb-4fd6-8ad6-87d2fc6387e5","gmt_create":"2026-08-14T18:44:06.2380949+10:00","gmt_modified":"2026-08-14T18:44:06.2448873+10:00"},{"catalog_id":"c34de209-e200-4523-a028-b7ee197969b3","title":"Resource Calculation Service","description":"resource-calculation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"f39634e8-6feb-40fc-9768-344eb9186ee9","gmt_create":"2026-08-14T18:44:10.5530618+10:00","gmt_modified":"2026-08-14T18:44:10.5588405+10:00"},{"catalog_id":"abf4996e-16c8-46c6-b4ad-37b49bb8c97d","title":"Cart Events and Listeners","description":"cart-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"2fe41d24-0d24-46ad-98fb-df79d8b27b3e","gmt_create":"2026-08-14T18:44:28.6567971+10:00","gmt_modified":"2026-08-14T18:44:28.6794473+10:00"},{"catalog_id":"913242e6-7d04-45ba-a668-73d34ddbb9d0","title":"Pricing Endpoints","description":"pricing-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"52362e7c-a29c-48b5-a121-0b96dfffcf2f","gmt_create":"2026-08-14T18:45:18.0483469+10:00","gmt_modified":"2026-08-14T18:45:18.0547461+10:00"},{"catalog_id":"7e59ce25-92a2-4b6e-b318-305975e4774c","title":"Reservation Management Endpoints","description":"reservation-management","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"5cba8ef2-84da-408b-a7c3-cd8446bdc98f","gmt_create":"2026-08-14T18:45:29.2467058+10:00","gmt_modified":"2026-08-14T18:45:29.2548347+10:00"},{"catalog_id":"e4440356-2ecf-4549-8210-5c3cf1b1a2e7","title":"Reservation Service","description":"reservation-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"a5435748-2119-4c51-be75-2fd8ff52c01a","gmt_create":"2026-08-14T18:46:01.7047629+10:00","gmt_modified":"2026-08-14T18:46:01.7137182+10:00"},{"catalog_id":"a191d7b6-ba0b-4866-8261-f94c5cd3c0e5","title":"Payment and Service Events","description":"payment-events","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"c369ac8b-b519-4da2-8d55-bf32c404a6ae","gmt_create":"2026-08-14T18:46:34.3130528+10:00","gmt_modified":"2026-08-14T18:46:34.3209892+10:00"},{"catalog_id":"d5d94dac-0c5c-4d8c-a1de-a4dffbfe1aa5","title":"Reservation Endpoints","description":"reservation-endpoints","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ec0ad9e8-7d9c-462b-a339-516dbb9234e3","gmt_create":"2026-08-14T18:46:46.3597638+10:00","gmt_modified":"2026-08-14T18:46:46.3671881+10:00"},{"catalog_id":"0137d01c-f5c8-4b0f-9a00-c3f58340cff9","title":"Node Selection Service","description":"node-selection-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0b25fb2d-b932-496f-b6c4-d4bc9bd91a08","gmt_create":"2026-08-14T18:47:04.1837676+10:00","gmt_modified":"2026-08-14T18:47:04.1962743+10:00"},{"catalog_id":"bb865521-1431-40fe-8fdd-d248c151919e","title":"Event Registration and Configuration","description":"event-registration","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"e02882bb-0384-4cdb-84f8-774469b89c09","gmt_create":"2026-08-14T18:47:44.0963803+10:00","gmt_modified":"2026-08-14T18:47:44.1111826+10:00"},{"catalog_id":"2c2143bb-a6f1-4903-bbec-853144163068","title":"Alert Service","description":"alert-service","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"ccb27e95-0867-425f-b0d9-148c2a46646e","gmt_create":"2026-08-14T18:48:01.1870607+10:00","gmt_modified":"2026-08-14T18:48:01.1963661+10:00"},{"catalog_id":"632eace8-7d7d-41e6-9c29-2c85e645491d","title":"Complete Checkout Flow Integration","description":"checkout-flow","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"0db89115-1be8-40f6-a930-ca751cc20e05","gmt_create":"2026-08-14T18:48:16.8273712+10:00","gmt_modified":"2026-08-14T18:48:16.8373835+10:00"},{"catalog_id":"675ef40f-cabb-4c8a-ae9a-4e18e2f7ea0f","title":"Supporting Services","description":"supporting-services","extend":"{}","progress_status":"completed","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","reference_count":0,"id":"84c24e35-8404-439b-ae58-deb60a3a485b","gmt_create":"2026-08-14T18:48:47.7414129+10:00","gmt_modified":"2026-08-14T18:48:47.7461706+10:00"}],"wiki_overview":{"content":"# Dynamic Pterodactyl Extension Overview\n\nDynamic Pterodactyl is a companion extension for Paymenter 1.5.7 and its built-in Pterodactyl provisioner. It adds server-owned complete-vector RAM, CPU, disk, and allocation quotes; deterministic node selection; durable checkout and upgrade commitments; capacity alerts; and operator diagnostics without exposing node identity to customers.\n\n## Current architecture\n\n- `PterodactylInventoryService` performs strict, paginated, fail-closed reads of locations, nodes, servers, and allocations.\n- `ResourceCalculationService` combines live inventory with local commitments and explicit per-node `NodeCapacityPolicy` records. Stock Pterodactyl does not supply CPU capacity.\n- Paymenter cart events create and cancel short-lived holds. Payment, provisioning, renewal, cancellation, and upgrade state are coordinated by the companion Paymenter lifecycle rather than public reservation endpoints or invoice/service-created listeners in this extension.\n- Paid commitments and allocation claims are durable and idempotent. Dynamic products fail closed on malformed, incomplete, duplicated, orphaned, or unavailable inventory.\n- The Pterodactyl application key and alert webhook URLs are encrypted at rest. Webhooks are restricted to revalidated public HTTPS endpoints with pinned DNS and no redirects or proxies.\n- Deployment remains paused until the exact extension and Paymenter companion commits are reviewed, merged, migrated, and a real-panel staging lifecycle canary passes.\n\n## Documentation status\n\n`Architecture Overview/Architecture Overview.md` is the canonical current guide. The other 41 Qoder pages are preserved historical snapshots with explicit banners so earlier documentation and source trails remain available without overriding the reconciled architecture.","gmt_create":"2026-08-14T18:27:43.9614238+10:00","gmt_modified":"2026-08-18T06:44:22.5011777+10:00","id":"50fd549e-249f-48b8-8a9e-2d30f0dc5e42","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_readme":{"content":"No readme file","gmt_create":"2026-08-14T18:26:55.7592208+10:00","gmt_modified":"2026-08-14T18:26:55.7592208+10:00","id":"9d36a6e4-42b9-4eb4-a05c-fe27cc67efbc","repo_id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e"},"wiki_repo":{"id":"82f4a940-d059-4f38-8f3d-5d4a66cec71e","name":"dynamic-pterodactyl","progress_status":"completed","wiki_present_status":"COMPLETED","optimized_catalog":"\".\\n├── Admin/\\n│ ├── Pages/{AuditLogPage,Dashboard,NodeMonitoring,SetupWizard}.php\\n│ └── Resources/{AlertConfigResource,NodeCapacityPolicyResource,ReservationResource}.php\\n├── Events/AlertDeliveryFailed.php\\n├── Http/\\n│ ├── Controllers/Api/{AvailabilityController,ResourceQuoteController,UpgradeQuoteController}.php\\n│ ├── Controllers/Api/Admin/{AdminCapacityController,AdminReservationController}.php\\n│ └── Middleware/EnsureUserIsAdmin.php\\n├── Listeners/{CartItemCreatedListener,CartItemDeletedListener}.php\\n├── Models/\\n│ ├── {AlertConfig,AlertDeliveryLog,AuditLog,NodeCapacityPolicy,ResourceReservation}.php\\n│ └── durable provisioning and upgrade lifecycle models\\n├── Notifications/\\n├── Policies/ResourceReservationPolicy.php\\n├── Services/\\n│ ├── {PterodactylInventoryService,ResourceCalculationService,ResourceQuoteService}.php\\n│ ├── {ReservationService,ReservationConfigurationService,UpgradeReservationService}.php\\n│ ├── {NodeSelectionService,NodeCapacityPolicyService,ConfigOptionSetupService}.php\\n│ ├── {AlertService,WebhookEndpointPolicy,SchedulerHealthService}.php\\n│ └── lifecycle integrity, audit, and operator-alert services\\n├── database/migrations/ # 22 forward migrations\\n├── resources/views/admin/\\n├── routes/api.php\\n├── tests/{Feature,Unit}/\\n├── .github/workflows/cross-repository-integration.yml\\n├── AGENTS.md\\n├── CLAUDE.md\\n├── DECISIONS.md\\n├── PROGRESS.md\\n├── DynamicPterodactyl.php\\n└── phpunit.xml\"","current_document_structure":"WikiEncrypted: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","catalogue_think_content":"WikiEncrypted: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","recovery_checkpoint":"wiki_generation_completed","last_commit_id":"fe20627c71984aef6676a21fc7445c4fa5a19911","last_commit_update":"2026-08-14T19:47:29.7066198+10:00","gmt_create":"2026-08-14T18:23:46.9403433+10:00","gmt_modified":"2026-08-18T06:45:47.5747448+10:00","extend_info":"{\"language\":\"en\",\"active\":true,\"branch\":\"agent/rebase-pr22-on-pr23\",\"shareStatus\":\"\",\"server_error_code\":\"\",\"cosy_version\":\"1.24.2\"}"}} \ No newline at end of file From 6ef0bb837d4deef6101c4bc978e6c7748667af65 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 09:40:32 +1000 Subject: [PATCH 93/95] ci: pin sanitized Paymenter companion --- .github/workflows/cross-repository-integration.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cross-repository-integration.yml b/.github/workflows/cross-repository-integration.yml index 2bbb29b..d9824aa 100644 --- a/.github/workflows/cross-repository-integration.yml +++ b/.github/workflows/cross-repository-integration.yml @@ -35,7 +35,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: e9707384a7ea8b012ec4e26f0a5e525b47eaa6cc + ref: d58ab220998947cbb05b3806484a69ed7a419def path: paymenter - name: Set up PHP @@ -96,7 +96,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: e9707384a7ea8b012ec4e26f0a5e525b47eaa6cc + ref: d58ab220998947cbb05b3806484a69ed7a419def path: paymenter - name: Set up PHP @@ -200,7 +200,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: ObsidianNetwork/Paymenter-Obsidian-Network - ref: e9707384a7ea8b012ec4e26f0a5e525b47eaa6cc + ref: d58ab220998947cbb05b3806484a69ed7a419def path: paymenter - name: Set up PHP From c8dcbb6f538b1d05fc569c9d73d3cf2868069ba0 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 09:44:04 +1000 Subject: [PATCH 94/95] chore: remove tracked session cache --- .opencode/cache/cortex-loop-compliance.json | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 .opencode/cache/cortex-loop-compliance.json diff --git a/.opencode/cache/cortex-loop-compliance.json b/.opencode/cache/cortex-loop-compliance.json deleted file mode 100644 index 66c44e7..0000000 --- a/.opencode/cache/cortex-loop-compliance.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "endedAt": "2026-07-25T09:03:14.804Z", - "durationMs": 3150617, - "totalToolCalls": 465, - "cortexCalls": 0, - "verbs": { - "reads": 0, - "ingests": 0, - "reconsolidations": 0, - "skillRetrieve": 0, - "skillStore": 0, - "skillExecuted": 0, - "reason": 0 - }, - "gaps": [ - "NO-CORTEX: 465 tool calls over 3151s with zero cortex_* usage - prior context never consulted, nothing captured." - ] -} \ No newline at end of file From 3aee81b36b2e6a443d85897779ffa489887367a0 Mon Sep 17 00:00:00 2001 From: Jordan <164892154+Jordanmuss99@users.noreply.github.com> Date: Tue, 18 Aug 2026 10:30:39 +1000 Subject: [PATCH 95/95] style: format standalone test bootstrap --- tests/LaravelTestCase.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/LaravelTestCase.php b/tests/LaravelTestCase.php index 30ab2dd..03a14fa 100644 --- a/tests/LaravelTestCase.php +++ b/tests/LaravelTestCase.php @@ -18,14 +18,14 @@ public function createApplication() { $paymenterBasePath = getenv('PAYMENTER_BASE_PATH'); $bootstrap = $paymenterBasePath - ? rtrim($paymenterBasePath, '/\\') . '/bootstrap/app.php' - : __DIR__ . '/../../../../bootstrap/app.php'; + ? rtrim($paymenterBasePath, '/\\').'/bootstrap/app.php' + : __DIR__.'/../../../../bootstrap/app.php'; - if (!file_exists($bootstrap)) { + if (! file_exists($bootstrap)) { $bootstrap = '/var/www/paymenter/bootstrap/app.php'; } - if (!file_exists($bootstrap)) { + if (! file_exists($bootstrap)) { throw new \RuntimeException('Unable to locate Paymenter bootstrap/app.php. Set PAYMENTER_BASE_PATH for standalone checkouts.'); }